mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-11 15:26:55 +03:00
Individual render size for pdf pages
This commit is contained in:
parent
c84de96ad9
commit
d30d80773d
@ -3,7 +3,7 @@ namespace NAPS2.Images;
|
||||
public class PdfRenderSize
|
||||
{
|
||||
public static readonly PdfRenderSize Default = FromDpi(300);
|
||||
|
||||
|
||||
public static PdfRenderSize FromDpi(float dpi)
|
||||
{
|
||||
return new PdfRenderSize { Dpi = dpi };
|
||||
@ -14,13 +14,55 @@ public class PdfRenderSize
|
||||
return new PdfRenderSize { Width = width, Height = height };
|
||||
}
|
||||
|
||||
public static PdfRenderSize FromIndividualPageSizes(IEnumerable<PdfRenderSize> pageSizes)
|
||||
{
|
||||
var pageSizesArray = pageSizes.ToArray();
|
||||
foreach (var pageSize in pageSizesArray)
|
||||
{
|
||||
if (pageSize.PageSizes != null) throw new ArgumentException("Individual page sizes can't be nested");
|
||||
}
|
||||
return new PdfRenderSize { PageSizes = pageSizesArray };
|
||||
}
|
||||
|
||||
private PdfRenderSize()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public float? Dpi { get; private init; }
|
||||
|
||||
|
||||
public int? Width { get; private init; }
|
||||
|
||||
|
||||
public int? Height { get; private init; }
|
||||
|
||||
public PdfRenderSize[]? PageSizes { get; set; }
|
||||
|
||||
public (int widthInPx, int heightInPx, int xDpi, int yDpi) GetDimensions(
|
||||
float widthInInches, float heightInInches, int pageIndex)
|
||||
{
|
||||
int widthInPx, heightInPx, xDpi, yDpi;
|
||||
var renderSize = PageSizes != null && pageIndex < PageSizes.Length ? PageSizes[pageIndex] : this;
|
||||
if (renderSize.PageSizes != null)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid render size");
|
||||
}
|
||||
if (renderSize.Dpi is { } dpi)
|
||||
{
|
||||
// Cap the resolution to 10k pixels in each dimension
|
||||
dpi = Math.Min(dpi, 10000 / heightInInches);
|
||||
dpi = Math.Min(dpi, 10000 / widthInInches);
|
||||
|
||||
widthInPx = (int) Math.Round(widthInInches * dpi);
|
||||
heightInPx = (int) Math.Round(heightInInches * dpi);
|
||||
xDpi = (int) Math.Round(dpi);
|
||||
yDpi = (int) Math.Round(dpi);
|
||||
}
|
||||
else
|
||||
{
|
||||
widthInPx = renderSize.Width!.Value;
|
||||
heightInPx = renderSize.Height!.Value;
|
||||
xDpi = (int) Math.Round(widthInPx / widthInInches * 72);
|
||||
yDpi = (int) Math.Round(widthInPx / heightInInches * 72);
|
||||
}
|
||||
return (widthInPx, heightInPx, xDpi, yDpi);
|
||||
}
|
||||
}
|
@ -31,6 +31,11 @@ public static class PdfAsserts
|
||||
Assert.Equal(1, CountText(text, filePath));
|
||||
}
|
||||
|
||||
public static void AssertDoesNotContainText(string text, string filePath)
|
||||
{
|
||||
Assert.Equal(0, CountText(text, filePath));
|
||||
}
|
||||
|
||||
private static int CountText(string text, string filePath)
|
||||
{
|
||||
Assert.True(File.Exists(filePath));
|
||||
@ -77,20 +82,16 @@ public static class PdfAsserts
|
||||
{
|
||||
Assert.True(File.Exists(filePath));
|
||||
var renderer = new PdfiumPdfRenderer();
|
||||
// TODO: Optimize?
|
||||
using var firstExpectedImage = TestImageContextFactory.Get().Load(expectedImages[0]);
|
||||
// TODO: Can/should we specify size per page?
|
||||
var actualImages = renderer.Render(TestImageContextFactory.Get(), filePath,
|
||||
PdfRenderSize.FromDimensions(firstExpectedImage.Width, firstExpectedImage.Height), password).ToList();
|
||||
// var actualImages = renderer.Render(
|
||||
// TestImageContextFactory.Get(),
|
||||
// filePath,
|
||||
// i => expectedImages.Length > i ? expectedImages[i].HorizontalResolution : 300).ToList();
|
||||
using var expectedImagesRendered =
|
||||
expectedImages.Select(data => TestImageContextFactory.Get().Load(data)).ToDisposableList();
|
||||
var renderSizes = PdfRenderSize.FromIndividualPageSizes(
|
||||
expectedImagesRendered.Select(image => PdfRenderSize.FromDimensions(image.Width, image.Height)));
|
||||
var actualImages = renderer.Render(TestImageContextFactory.Get(), filePath, renderSizes, password).ToList();
|
||||
Assert.Equal(expectedImages.Length, actualImages.Count);
|
||||
for (int i = 0; i < expectedImages.Length; i++)
|
||||
{
|
||||
// TODO: Try and fix resolution here
|
||||
ImageAsserts.Similar(expectedImages[i], actualImages[i], ignoreResolution: true);
|
||||
ImageAsserts.Similar(expectedImagesRendered[i], actualImages[i], ignoreResolution: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,36 +56,17 @@ public class PdfiumPdfRenderer : IPdfRenderer
|
||||
yield return image;
|
||||
continue;
|
||||
}
|
||||
yield return RenderPageToNewImage(imageContext, page, renderSize);
|
||||
yield return RenderPageToNewImage(imageContext, page, pageIndex, renderSize);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe IMemoryImage RenderPageToNewImage(ImageContext imageContext, PdfPage page, PdfRenderSize renderSize)
|
||||
public unsafe IMemoryImage RenderPageToNewImage(ImageContext imageContext, PdfPage page, int pageIndex,
|
||||
PdfRenderSize renderSize)
|
||||
{
|
||||
var widthInInches = page.Width / 72;
|
||||
var heightInInches = page.Height / 72;
|
||||
|
||||
int widthInPx, heightInPx;
|
||||
int xDpi, yDpi;
|
||||
if (renderSize.Dpi != null)
|
||||
{
|
||||
// Cap the resolution to 10k pixels in each dimension
|
||||
var dpi = renderSize.Dpi.Value;
|
||||
dpi = Math.Min(dpi, 10000 / heightInInches);
|
||||
dpi = Math.Min(dpi, 10000 / widthInInches);
|
||||
|
||||
widthInPx = (int) Math.Round(widthInInches * dpi);
|
||||
heightInPx = (int) Math.Round(heightInInches * dpi);
|
||||
xDpi = (int) Math.Round(dpi);
|
||||
yDpi = (int) Math.Round(dpi);
|
||||
}
|
||||
else
|
||||
{
|
||||
widthInPx = renderSize.Width!.Value;
|
||||
heightInPx = renderSize.Height!.Value;
|
||||
xDpi = (int) Math.Round(widthInPx / widthInInches * 72);
|
||||
yDpi = (int) Math.Round(widthInPx / heightInInches * 72);
|
||||
}
|
||||
var (widthInPx, heightInPx, xDpi, yDpi) = renderSize.GetDimensions(widthInInches, heightInInches, pageIndex);
|
||||
|
||||
var bitmap = imageContext.Create(widthInPx, heightInPx, ImagePixelFormat.RGB24);
|
||||
bitmap.SetResolution(xDpi, yDpi);
|
||||
|
Loading…
Reference in New Issue
Block a user