Skip to content

Commit

Permalink
Provide IPdfRenderer from ProcessedImage
Browse files Browse the repository at this point in the history
  • Loading branch information
cyanfish committed Feb 7, 2024
1 parent 80dc5c0 commit 8906f5b
Show file tree
Hide file tree
Showing 13 changed files with 45 additions and 35 deletions.
6 changes: 1 addition & 5 deletions NAPS2.Images.Gdi/GdiImageContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion NAPS2.Images.Gtk/GtkImageContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion NAPS2.Images.ImageSharp/ImageSharpImageContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static Configuration GetConfiguration()
Configuration = GetConfiguration()
};

public ImageSharpImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(ImageSharpImage), pdfRenderer)
public ImageSharpImageContext() : base(typeof(ImageSharpImage))
{
_imageTransformer = new ImageSharpImageTransformer(this);
}
Expand Down
2 changes: 1 addition & 1 deletion NAPS2.Images.Mac/MacImageContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion NAPS2.Images.Wpf/WpfImageContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 2 additions & 0 deletions NAPS2.Images/IMemoryImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ namespace NAPS2.Images;
/// </summary>
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.
/// <summary>
/// Gets the image context used to create this image.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions NAPS2.Images/IPdfRendererProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace NAPS2.Images;

public interface IPdfRendererProvider
{
IPdfRenderer PdfRenderer { get; }
}
34 changes: 18 additions & 16 deletions NAPS2.Images/ImageContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -43,40 +41,39 @@ private static ImageFileFormat GetFileFormatFromFirstBytes(Stream stream)
};
}

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;
}
Expand Down Expand Up @@ -239,22 +236,27 @@ public void CheckSupportsFormat(ImageFileFormat format)

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!;
}
Expand Down
2 changes: 1 addition & 1 deletion NAPS2.Sdk.Tests/ContextualTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public ContextualTests()
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);
Expand Down
4 changes: 2 additions & 2 deletions NAPS2.Sdk.Tests/Images/ImageSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public async Task PdfDeserializeToFileStorage(StorageConfig config)
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);
Expand Down Expand Up @@ -340,7 +340,7 @@ public void IncludeThumbnail_InvalidTransformState()

private ScanningContext CreateDestContextWithFileStorage()
{
return new ScanningContext(TestImageContextFactory.Get(new PdfiumPdfRenderer()))
return new ScanningContext(TestImageContextFactory.Get())
{
FileStorageManager = FileStorageManager.CreateFolder(Path.Combine(FolderPath, "dest"))
};
Expand Down
10 changes: 5 additions & 5 deletions NAPS2.Sdk.Tests/TestImageContextFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
6 changes: 5 additions & 1 deletion NAPS2.Sdk/Images/ProcessedImage.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using NAPS2.Pdf;

namespace NAPS2.Images;

/// <summary>
Expand All @@ -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).
/// </summary>
public class ProcessedImage : IRenderableImage, IDisposable, IEquatable<ProcessedImage>
public class ProcessedImage : IRenderableImage, IPdfRendererProvider, IDisposable, IEquatable<ProcessedImage>
{
private readonly RefCount.Token _token;
private bool _disposed;
Expand Down Expand Up @@ -189,4 +191,6 @@ public void Dispose()
/// at any moment.
/// </param>
public record WeakReference(ProcessedImage ProcessedImage);

IPdfRenderer IPdfRendererProvider.PdfRenderer => new PdfiumPdfRenderer();
}
2 changes: 1 addition & 1 deletion NAPS2.Sdk/Images/ThumbnailRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public ThumbnailRenderer(ImageContext imageContext)

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)
{
Expand Down

0 comments on commit 8906f5b

Please sign in to comment.