mirror of
https://github.com/cyanfish/naps2.git
synced 2024-10-27 01:22:49 +03:00
Provide IPdfRenderer from ProcessedImage
This commit is contained in:
parent
80dc5c0635
commit
8906f5b76e
@ -11,11 +11,7 @@ public class GdiImageContext : ImageContext
|
|||||||
{
|
{
|
||||||
private readonly GdiImageTransformer _imageTransformer;
|
private readonly GdiImageTransformer _imageTransformer;
|
||||||
|
|
||||||
public GdiImageContext() : this(null)
|
public GdiImageContext() : base(typeof(GdiImage))
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public GdiImageContext(IPdfRenderer? pdfRenderer) : base(typeof(GdiImage), pdfRenderer)
|
|
||||||
{
|
{
|
||||||
_imageTransformer = new GdiImageTransformer(this);
|
_imageTransformer = new GdiImageTransformer(this);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ public class GtkImageContext : ImageContext
|
|||||||
private readonly GtkImageTransformer _imageTransformer;
|
private readonly GtkImageTransformer _imageTransformer;
|
||||||
private readonly LibTiffIo _tiffIo;
|
private readonly LibTiffIo _tiffIo;
|
||||||
|
|
||||||
public GtkImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(GtkImage), pdfRenderer)
|
public GtkImageContext() : base(typeof(GtkImage))
|
||||||
{
|
{
|
||||||
_imageTransformer = new GtkImageTransformer(this);
|
_imageTransformer = new GtkImageTransformer(this);
|
||||||
_tiffIo = new LibTiffIo(this);
|
_tiffIo = new LibTiffIo(this);
|
||||||
|
@ -21,7 +21,7 @@ public class ImageSharpImageContext : ImageContext
|
|||||||
Configuration = GetConfiguration()
|
Configuration = GetConfiguration()
|
||||||
};
|
};
|
||||||
|
|
||||||
public ImageSharpImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(ImageSharpImage), pdfRenderer)
|
public ImageSharpImageContext() : base(typeof(ImageSharpImage))
|
||||||
{
|
{
|
||||||
_imageTransformer = new ImageSharpImageTransformer(this);
|
_imageTransformer = new ImageSharpImageTransformer(this);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ public class MacImageContext : ImageContext
|
|||||||
|
|
||||||
private readonly MacImageTransformer _imageTransformer;
|
private readonly MacImageTransformer _imageTransformer;
|
||||||
|
|
||||||
public MacImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(MacImage), pdfRenderer)
|
public MacImageContext() : base(typeof(MacImage))
|
||||||
{
|
{
|
||||||
NSApplication.CheckForIllegalCrossThreadCalls = false;
|
NSApplication.CheckForIllegalCrossThreadCalls = false;
|
||||||
_imageTransformer = new MacImageTransformer(this);
|
_imageTransformer = new MacImageTransformer(this);
|
||||||
|
@ -9,7 +9,7 @@ public class WpfImageContext : ImageContext
|
|||||||
{
|
{
|
||||||
private readonly WpfImageTransformer _imageTransformer;
|
private readonly WpfImageTransformer _imageTransformer;
|
||||||
|
|
||||||
public WpfImageContext(IPdfRenderer? pdfRenderer = null) : base(typeof(WpfImage), pdfRenderer)
|
public WpfImageContext() : base(typeof(WpfImage))
|
||||||
{
|
{
|
||||||
_imageTransformer = new WpfImageTransformer(this);
|
_imageTransformer = new WpfImageTransformer(this);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ namespace NAPS2.Images;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMemoryImage : IImageStorage
|
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>
|
/// <summary>
|
||||||
/// Gets the image context used to create this image.
|
/// Gets the image context used to create this image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
6
NAPS2.Images/IPdfRendererProvider.cs
Normal file
6
NAPS2.Images/IPdfRendererProvider.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
namespace NAPS2.Images;
|
||||||
|
|
||||||
|
public interface IPdfRendererProvider
|
||||||
|
{
|
||||||
|
IPdfRenderer PdfRenderer { get; }
|
||||||
|
}
|
@ -5,8 +5,6 @@ namespace NAPS2.Images;
|
|||||||
|
|
||||||
public abstract class ImageContext
|
public abstract class ImageContext
|
||||||
{
|
{
|
||||||
private readonly IPdfRenderer? _pdfRenderer;
|
|
||||||
|
|
||||||
public static ImageFileFormat GetFileFormatFromExtension(string path)
|
public static ImageFileFormat GetFileFormatFromExtension(string path)
|
||||||
{
|
{
|
||||||
return Path.GetExtension(path).ToLowerInvariant() switch
|
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;
|
ImageType = imageType;
|
||||||
_pdfRenderer = pdfRenderer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add NotNullWhen attribute?
|
// 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 (Path.GetExtension(fileStorage.FullPath).ToLowerInvariant() == ".pdf")
|
||||||
{
|
{
|
||||||
if (_pdfRenderer == null)
|
if (pdfRenderer == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
renderedPdf = null;
|
renderedPdf = null;
|
||||||
return false;
|
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 (memoryStorage.TypeHint == ".pdf")
|
||||||
{
|
{
|
||||||
if (_pdfRenderer == null)
|
if (pdfRenderer == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
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;
|
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();
|
.Single();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -239,22 +236,27 @@ public abstract class ImageContext
|
|||||||
|
|
||||||
public IMemoryImage Render(IRenderableImage image)
|
public IMemoryImage Render(IRenderableImage image)
|
||||||
{
|
{
|
||||||
var bitmap = RenderFromStorage(image.Storage);
|
var bitmap = RenderWithoutTransforms(image);
|
||||||
return PerformAllTransforms(bitmap, image.TransformState.Transforms);
|
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)
|
switch (storage)
|
||||||
{
|
{
|
||||||
case ImageFileStorage fileStorage:
|
case ImageFileStorage fileStorage:
|
||||||
if (MaybeRenderPdf(fileStorage, out var renderedPdf))
|
if (MaybeRenderPdf(fileStorage, pdfRenderer, out var renderedPdf))
|
||||||
{
|
{
|
||||||
return renderedPdf!;
|
return renderedPdf!;
|
||||||
}
|
}
|
||||||
return Load(fileStorage.FullPath);
|
return Load(fileStorage.FullPath);
|
||||||
case ImageMemoryStorage memoryStorage:
|
case ImageMemoryStorage memoryStorage:
|
||||||
if (MaybeRenderPdf(memoryStorage, out var renderedMemoryPdf))
|
if (MaybeRenderPdf(memoryStorage, pdfRenderer, out var renderedMemoryPdf))
|
||||||
{
|
{
|
||||||
return renderedMemoryPdf!;
|
return renderedMemoryPdf!;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ public class ContextualTests : IDisposable
|
|||||||
FolderPath = Path.GetFullPath(Path.Combine("naps2_test_temp", Path.GetRandomFileName()));
|
FolderPath = Path.GetFullPath(Path.Combine("naps2_test_temp", Path.GetRandomFileName()));
|
||||||
Folder = Directory.CreateDirectory(FolderPath);
|
Folder = Directory.CreateDirectory(FolderPath);
|
||||||
|
|
||||||
ImageContext = TestImageContextFactory.Get(new PdfiumPdfRenderer());
|
ImageContext = TestImageContextFactory.Get();
|
||||||
ScanningContext = new ScanningContext(ImageContext);
|
ScanningContext = new ScanningContext(ImageContext);
|
||||||
ScanningContext.TempFolderPath = Path.Combine(FolderPath, "temp");
|
ScanningContext.TempFolderPath = Path.Combine(FolderPath, "temp");
|
||||||
Directory.CreateDirectory(ScanningContext.TempFolderPath);
|
Directory.CreateDirectory(ScanningContext.TempFolderPath);
|
||||||
|
@ -278,7 +278,7 @@ public class ImageSerializerTests : ContextualTests
|
|||||||
public async Task PdfDeserializeToMemoryStorage(StorageConfig config)
|
public async Task PdfDeserializeToMemoryStorage(StorageConfig config)
|
||||||
{
|
{
|
||||||
config.Apply(this);
|
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");
|
var importPath = Path.Combine(FolderPath, "import.pdf");
|
||||||
File.WriteAllBytes(importPath, PdfResources.word_generated_pdf);
|
File.WriteAllBytes(importPath, PdfResources.word_generated_pdf);
|
||||||
@ -340,7 +340,7 @@ public class ImageSerializerTests : ContextualTests
|
|||||||
|
|
||||||
private ScanningContext CreateDestContextWithFileStorage()
|
private ScanningContext CreateDestContextWithFileStorage()
|
||||||
{
|
{
|
||||||
return new ScanningContext(TestImageContextFactory.Get(new PdfiumPdfRenderer()))
|
return new ScanningContext(TestImageContextFactory.Get())
|
||||||
{
|
{
|
||||||
FileStorageManager = FileStorageManager.CreateFolder(Path.Combine(FolderPath, "dest"))
|
FileStorageManager = FileStorageManager.CreateFolder(Path.Combine(FolderPath, "dest"))
|
||||||
};
|
};
|
||||||
|
@ -2,18 +2,18 @@ namespace NAPS2.Sdk.Tests;
|
|||||||
|
|
||||||
public static class TestImageContextFactory
|
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
|
// 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.
|
// more comprehensive, i.e. set up some IMAGESHARP/SKIA compiler variables and have special test commands.
|
||||||
#if MAC
|
#if MAC
|
||||||
return new NAPS2.Images.Mac.MacImageContext(pdfRenderer);
|
return new NAPS2.Images.Mac.MacImageContext();
|
||||||
#elif LINUX
|
#elif LINUX
|
||||||
return new NAPS2.Images.Gtk.GtkImageContext(pdfRenderer);
|
return new NAPS2.Images.Gtk.GtkImageContext();
|
||||||
#elif NET6_0_OR_GREATER
|
#elif NET6_0_OR_GREATER
|
||||||
return new NAPS2.Images.ImageSharp.ImageSharpImageContext(pdfRenderer);
|
return new NAPS2.Images.ImageSharp.ImageSharpImageContext();
|
||||||
#else
|
#else
|
||||||
return new NAPS2.Images.Gdi.GdiImageContext(pdfRenderer);
|
return new NAPS2.Images.Gdi.GdiImageContext();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
using NAPS2.Pdf;
|
||||||
|
|
||||||
namespace NAPS2.Images;
|
namespace NAPS2.Images;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -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
|
/// 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).
|
/// all related instances are disposed (or the parent ScanningContext is disposed).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProcessedImage : IRenderableImage, IDisposable, IEquatable<ProcessedImage>
|
public class ProcessedImage : IRenderableImage, IPdfRendererProvider, IDisposable, IEquatable<ProcessedImage>
|
||||||
{
|
{
|
||||||
private readonly RefCount.Token _token;
|
private readonly RefCount.Token _token;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
@ -189,4 +191,6 @@ public class ProcessedImage : IRenderableImage, IDisposable, IEquatable<Processe
|
|||||||
/// at any moment.
|
/// at any moment.
|
||||||
/// </param>
|
/// </param>
|
||||||
public record WeakReference(ProcessedImage ProcessedImage);
|
public record WeakReference(ProcessedImage ProcessedImage);
|
||||||
|
|
||||||
|
IPdfRenderer IPdfRendererProvider.PdfRenderer => new PdfiumPdfRenderer();
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ public class ThumbnailRenderer
|
|||||||
|
|
||||||
public IMemoryImage Render(ProcessedImage processedImage, int outputSize)
|
public IMemoryImage Render(ProcessedImage processedImage, int outputSize)
|
||||||
{
|
{
|
||||||
var image = _imageContext.RenderFromStorage(processedImage.Storage);
|
var image = _imageContext.RenderWithoutTransforms(processedImage);
|
||||||
var transformList = processedImage.TransformState.Transforms;
|
var transformList = processedImage.TransformState.Transforms;
|
||||||
if (!processedImage.TransformState.IsEmpty)
|
if (!processedImage.TransformState.IsEmpty)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user