diff --git a/NAPS2.Images.Gdi/GdiImageContext.cs b/NAPS2.Images.Gdi/GdiImageContext.cs
index 7dc8234cf..e8585f3a0 100644
--- a/NAPS2.Images.Gdi/GdiImageContext.cs
+++ b/NAPS2.Images.Gdi/GdiImageContext.cs
@@ -11,11 +11,7 @@ public class GdiImageContext : ImageContext
{
private readonly GdiImageTransformer _imageTransformer;
- public GdiImageContext() : this(null)
- {
- }
-
- public GdiImageContext(IPdfRenderer? pdfRenderer) : base(typeof(GdiImage), pdfRenderer)
+ public GdiImageContext() : base(typeof(GdiImage))
{
_imageTransformer = new GdiImageTransformer(this);
}
diff --git a/NAPS2.Images.Gtk/GtkImageContext.cs b/NAPS2.Images.Gtk/GtkImageContext.cs
index f2c8f3a85..71b1f0368 100644
--- a/NAPS2.Images.Gtk/GtkImageContext.cs
+++ b/NAPS2.Images.Gtk/GtkImageContext.cs
@@ -9,7 +9,7 @@ public class GtkImageContext : ImageContext
private readonly GtkImageTransformer _imageTransformer;
private readonly LibTiffIo _tiffIo;
- public GtkImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(GtkImage), pdfRenderer)
+ public GtkImageContext() : base(typeof(GtkImage))
{
_imageTransformer = new GtkImageTransformer(this);
_tiffIo = new LibTiffIo(this);
diff --git a/NAPS2.Images.ImageSharp/ImageSharpImageContext.cs b/NAPS2.Images.ImageSharp/ImageSharpImageContext.cs
index e1ccbb667..0bd6fead5 100644
--- a/NAPS2.Images.ImageSharp/ImageSharpImageContext.cs
+++ b/NAPS2.Images.ImageSharp/ImageSharpImageContext.cs
@@ -21,7 +21,7 @@ public class ImageSharpImageContext : ImageContext
Configuration = GetConfiguration()
};
- public ImageSharpImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(ImageSharpImage), pdfRenderer)
+ public ImageSharpImageContext() : base(typeof(ImageSharpImage))
{
_imageTransformer = new ImageSharpImageTransformer(this);
}
diff --git a/NAPS2.Images.Mac/MacImageContext.cs b/NAPS2.Images.Mac/MacImageContext.cs
index e480fa2a0..46b1d1e68 100644
--- a/NAPS2.Images.Mac/MacImageContext.cs
+++ b/NAPS2.Images.Mac/MacImageContext.cs
@@ -9,7 +9,7 @@ public class MacImageContext : ImageContext
private readonly MacImageTransformer _imageTransformer;
- public MacImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(MacImage), pdfRenderer)
+ public MacImageContext() : base(typeof(MacImage))
{
NSApplication.CheckForIllegalCrossThreadCalls = false;
_imageTransformer = new MacImageTransformer(this);
diff --git a/NAPS2.Images.Wpf/WpfImageContext.cs b/NAPS2.Images.Wpf/WpfImageContext.cs
index 818166b54..22a0335ae 100644
--- a/NAPS2.Images.Wpf/WpfImageContext.cs
+++ b/NAPS2.Images.Wpf/WpfImageContext.cs
@@ -9,7 +9,7 @@ public class WpfImageContext : ImageContext
{
private readonly WpfImageTransformer _imageTransformer;
- public WpfImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(WpfImage), pdfRenderer)
+ public WpfImageContext() : base(typeof(WpfImage))
{
_imageTransformer = new WpfImageTransformer(this);
}
diff --git a/NAPS2.Images/IMemoryImage.cs b/NAPS2.Images/IMemoryImage.cs
index 4b4ea01a0..2ebf25798 100644
--- a/NAPS2.Images/IMemoryImage.cs
+++ b/NAPS2.Images/IMemoryImage.cs
@@ -8,6 +8,8 @@ namespace NAPS2.Images;
///
public interface IMemoryImage : IImageStorage
{
+ // TODO: Now that ImageContext objects are fully stateless, we can maybe eliminate ImageContext as a parameter
+ // in IMemoryImage constructors and just create the appropriate ImageContext objects automatically.
///
/// Gets the image context used to create this image.
///
diff --git a/NAPS2.Images/IPdfRendererProvider.cs b/NAPS2.Images/IPdfRendererProvider.cs
new file mode 100644
index 000000000..4defe199c
--- /dev/null
+++ b/NAPS2.Images/IPdfRendererProvider.cs
@@ -0,0 +1,6 @@
+namespace NAPS2.Images;
+
+public interface IPdfRendererProvider
+{
+ IPdfRenderer PdfRenderer { get; }
+}
\ No newline at end of file
diff --git a/NAPS2.Images/ImageContext.cs b/NAPS2.Images/ImageContext.cs
index 7b2fdc327..78f19fb6b 100644
--- a/NAPS2.Images/ImageContext.cs
+++ b/NAPS2.Images/ImageContext.cs
@@ -5,8 +5,6 @@ namespace NAPS2.Images;
public abstract class ImageContext
{
- private readonly IPdfRenderer? _pdfRenderer;
-
public static ImageFileFormat GetFileFormatFromExtension(string path)
{
return Path.GetExtension(path).ToLowerInvariant() switch
@@ -43,40 +41,39 @@ public abstract class ImageContext
};
}
- protected ImageContext(Type imageType, IPdfRenderer? pdfRenderer = null)
+ protected ImageContext(Type imageType)
{
ImageType = imageType;
- _pdfRenderer = pdfRenderer;
}
// TODO: Add NotNullWhen attribute?
- private bool MaybeRenderPdf(ImageFileStorage fileStorage, out IMemoryImage? renderedPdf)
+ private bool MaybeRenderPdf(ImageFileStorage fileStorage, IPdfRenderer? pdfRenderer, out IMemoryImage? renderedPdf)
{
if (Path.GetExtension(fileStorage.FullPath).ToLowerInvariant() == ".pdf")
{
- if (_pdfRenderer == null)
+ if (pdfRenderer == null)
{
throw new InvalidOperationException(
- "Unable to render pdf page as the ImageContext wasn't created with an IPdfRenderer.");
+ "Unable to render pdf page as the IRenderableImage didn't implement IPdfRendererProvider.");
}
- renderedPdf = _pdfRenderer.Render(this, fileStorage.FullPath, PdfRenderSize.Default).Single();
+ renderedPdf = pdfRenderer.Render(this, fileStorage.FullPath, PdfRenderSize.Default).Single();
return true;
}
renderedPdf = null;
return false;
}
- private bool MaybeRenderPdf(ImageMemoryStorage memoryStorage, out IMemoryImage? renderedPdf)
+ private bool MaybeRenderPdf(ImageMemoryStorage memoryStorage, IPdfRenderer? pdfRenderer, out IMemoryImage? renderedPdf)
{
if (memoryStorage.TypeHint == ".pdf")
{
- if (_pdfRenderer == null)
+ if (pdfRenderer == null)
{
throw new InvalidOperationException(
- "Unable to render pdf page as the ImageContext wasn't created with an IPdfRenderer.");
+ "Unable to render pdf page as the IRenderableImage didn't implement IPdfRendererProvider.");
}
var stream = memoryStorage.Stream;
- renderedPdf = _pdfRenderer.Render(this, stream.GetBuffer(), (int) stream.Length, PdfRenderSize.Default)
+ renderedPdf = pdfRenderer.Render(this, stream.GetBuffer(), (int) stream.Length, PdfRenderSize.Default)
.Single();
return true;
}
@@ -239,22 +236,27 @@ public abstract class ImageContext
public IMemoryImage Render(IRenderableImage image)
{
- var bitmap = RenderFromStorage(image.Storage);
+ var bitmap = RenderWithoutTransforms(image);
return PerformAllTransforms(bitmap, image.TransformState.Transforms);
}
- public IMemoryImage RenderFromStorage(IImageStorage storage)
+ public IMemoryImage RenderWithoutTransforms(IRenderableImage image)
+ {
+ return RenderFromStorage(image.Storage, (image as IPdfRendererProvider)?.PdfRenderer);
+ }
+
+ private IMemoryImage RenderFromStorage(IImageStorage storage, IPdfRenderer pdfRenderer)
{
switch (storage)
{
case ImageFileStorage fileStorage:
- if (MaybeRenderPdf(fileStorage, out var renderedPdf))
+ if (MaybeRenderPdf(fileStorage, pdfRenderer, out var renderedPdf))
{
return renderedPdf!;
}
return Load(fileStorage.FullPath);
case ImageMemoryStorage memoryStorage:
- if (MaybeRenderPdf(memoryStorage, out var renderedMemoryPdf))
+ if (MaybeRenderPdf(memoryStorage, pdfRenderer, out var renderedMemoryPdf))
{
return renderedMemoryPdf!;
}
diff --git a/NAPS2.Sdk.Tests/ContextualTests.cs b/NAPS2.Sdk.Tests/ContextualTests.cs
index 77f03af6f..3e876cbf4 100644
--- a/NAPS2.Sdk.Tests/ContextualTests.cs
+++ b/NAPS2.Sdk.Tests/ContextualTests.cs
@@ -18,7 +18,7 @@ public class ContextualTests : IDisposable
FolderPath = Path.GetFullPath(Path.Combine("naps2_test_temp", Path.GetRandomFileName()));
Folder = Directory.CreateDirectory(FolderPath);
- ImageContext = TestImageContextFactory.Get(new PdfiumPdfRenderer());
+ ImageContext = TestImageContextFactory.Get();
ScanningContext = new ScanningContext(ImageContext);
ScanningContext.TempFolderPath = Path.Combine(FolderPath, "temp");
Directory.CreateDirectory(ScanningContext.TempFolderPath);
diff --git a/NAPS2.Sdk.Tests/Images/ImageSerializerTests.cs b/NAPS2.Sdk.Tests/Images/ImageSerializerTests.cs
index 63e575fa9..7b52b98f3 100644
--- a/NAPS2.Sdk.Tests/Images/ImageSerializerTests.cs
+++ b/NAPS2.Sdk.Tests/Images/ImageSerializerTests.cs
@@ -278,7 +278,7 @@ public class ImageSerializerTests : ContextualTests
public async Task PdfDeserializeToMemoryStorage(StorageConfig config)
{
config.Apply(this);
- using var destContext = new ScanningContext(TestImageContextFactory.Get(new PdfiumPdfRenderer()));
+ using var destContext = new ScanningContext(TestImageContextFactory.Get());
var importPath = Path.Combine(FolderPath, "import.pdf");
File.WriteAllBytes(importPath, PdfResources.word_generated_pdf);
@@ -340,7 +340,7 @@ public class ImageSerializerTests : ContextualTests
private ScanningContext CreateDestContextWithFileStorage()
{
- return new ScanningContext(TestImageContextFactory.Get(new PdfiumPdfRenderer()))
+ return new ScanningContext(TestImageContextFactory.Get())
{
FileStorageManager = FileStorageManager.CreateFolder(Path.Combine(FolderPath, "dest"))
};
diff --git a/NAPS2.Sdk.Tests/TestImageContextFactory.cs b/NAPS2.Sdk.Tests/TestImageContextFactory.cs
index c2dec6802..9fb9505fd 100644
--- a/NAPS2.Sdk.Tests/TestImageContextFactory.cs
+++ b/NAPS2.Sdk.Tests/TestImageContextFactory.cs
@@ -2,18 +2,18 @@ namespace NAPS2.Sdk.Tests;
public static class TestImageContextFactory
{
- public static ImageContext Get(IPdfRenderer pdfRenderer = null)
+ public static ImageContext Get()
{
// TODO: For now we use ImageSharp on net6-windows for coverage. But eventually we'll need to do something
// more comprehensive, i.e. set up some IMAGESHARP/SKIA compiler variables and have special test commands.
#if MAC
- return new NAPS2.Images.Mac.MacImageContext(pdfRenderer);
+ return new NAPS2.Images.Mac.MacImageContext();
#elif LINUX
- return new NAPS2.Images.Gtk.GtkImageContext(pdfRenderer);
+ return new NAPS2.Images.Gtk.GtkImageContext();
#elif NET6_0_OR_GREATER
- return new NAPS2.Images.ImageSharp.ImageSharpImageContext(pdfRenderer);
+ return new NAPS2.Images.ImageSharp.ImageSharpImageContext();
#else
- return new NAPS2.Images.Gdi.GdiImageContext(pdfRenderer);
+ return new NAPS2.Images.Gdi.GdiImageContext();
#endif
}
}
\ No newline at end of file
diff --git a/NAPS2.Sdk/Images/ProcessedImage.cs b/NAPS2.Sdk/Images/ProcessedImage.cs
index 86e137f98..05b42e395 100644
--- a/NAPS2.Sdk/Images/ProcessedImage.cs
+++ b/NAPS2.Sdk/Images/ProcessedImage.cs
@@ -1,3 +1,5 @@
+using NAPS2.Pdf;
+
namespace NAPS2.Images;
///
@@ -9,7 +11,7 @@ namespace NAPS2.Images;
/// reference with Clone() that will need to be disposed, and the underlying image storage will only be disposed once
/// all related instances are disposed (or the parent ScanningContext is disposed).
///
-public class ProcessedImage : IRenderableImage, IDisposable, IEquatable
+public class ProcessedImage : IRenderableImage, IPdfRendererProvider, IDisposable, IEquatable
{
private readonly RefCount.Token _token;
private bool _disposed;
@@ -189,4 +191,6 @@ public class ProcessedImage : IRenderableImage, IDisposable, IEquatable
public record WeakReference(ProcessedImage ProcessedImage);
+
+ IPdfRenderer IPdfRendererProvider.PdfRenderer => new PdfiumPdfRenderer();
}
\ No newline at end of file
diff --git a/NAPS2.Sdk/Images/ThumbnailRenderer.cs b/NAPS2.Sdk/Images/ThumbnailRenderer.cs
index 6ac359e8e..957a5341f 100644
--- a/NAPS2.Sdk/Images/ThumbnailRenderer.cs
+++ b/NAPS2.Sdk/Images/ThumbnailRenderer.cs
@@ -17,7 +17,7 @@ public class ThumbnailRenderer
public IMemoryImage Render(ProcessedImage processedImage, int outputSize)
{
- var image = _imageContext.RenderFromStorage(processedImage.Storage);
+ var image = _imageContext.RenderWithoutTransforms(processedImage);
var transformList = processedImage.TransformState.Transforms;
if (!processedImage.TransformState.IsEmpty)
{