Pdfium renderer impl (untested)

This commit is contained in:
Ben Olden-Cooligan 2019-04-12 20:29:05 -04:00
parent b8588e5f9d
commit 2f4cb33cca
7 changed files with 132 additions and 7 deletions

View File

@ -34,7 +34,7 @@ namespace NAPS2.Modules
Bind<IScannedImageImporter>().To<ScannedImageImporter>();
Bind<IPdfImporter>().To<PdfSharpImporter>();
Bind<IImageImporter>().To<ImageImporter>();
Bind<IPdfRenderer>().To<GhostscriptPdfRenderer>().InSingletonScope();
Bind<IPdfRenderer>().To<PdfiumPdfRenderer>().InSingletonScope();
// Export
Bind<PdfExporter>().To<PdfSharpExporter>();

View File

@ -36,8 +36,8 @@ namespace NAPS2.Images.Storage
// Then we can have a PDF->Image converter that returns null if it's not a pdf file.
if (IsPdfFile(input))
{
var renderer = new GhostscriptPdfRenderer(null);
return new GdiImage(renderer.Render(input.FullPath).Single());
var renderer = new PdfiumPdfRenderer();
return (GdiImage)renderer.Render(input.FullPath).Single();
}
else
{

View File

@ -6,6 +6,7 @@ using System.Linq;
using Ghostscript.NET.Rasterizer;
using NAPS2.Config.Experimental;
using NAPS2.Dependencies;
using NAPS2.Images.Storage;
using NAPS2.Lang.Resources;
using NAPS2.Scan;
using NAPS2.Util;
@ -24,7 +25,7 @@ namespace NAPS2.ImportExport.Pdf
this.configProvider = configProvider;
}
public IEnumerable<Bitmap> Render(string path)
public IEnumerable<IImage> Render(string path)
{
// TODO
// ThrowIfCantRender();
@ -53,7 +54,7 @@ namespace NAPS2.ImportExport.Pdf
{
var bitmap = (Bitmap)rasterizer.GetPage(dpi, dpi, pageNumber);
bitmap.SafeSetResolution(dpi, dpi);
yield return bitmap;
yield return new GdiImage(bitmap);
}
}
}

View File

@ -1,14 +1,14 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using NAPS2.Dependencies;
using NAPS2.Images.Storage;
namespace NAPS2.ImportExport.Pdf
{
public interface IPdfRenderer
{
IEnumerable<Bitmap> Render(string path);
IEnumerable<IImage> Render(string path);
void ThrowIfCantRender();
void PromptToInstallIfNeeded(IComponentInstallPrompt componentInstallPrompt);
}

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using NAPS2.Platform;
using NAPS2.Util;
namespace NAPS2.ImportExport.Pdf
{
public class PdfiumNativeMethods
{
public const int FPDFBitmap_BGR = 2;
public const int FPDFBitmap_BGRA = 4;
public const int FPDF_PRINTING = 0x800;
public const int FPDF_REVERSE_BYTE_ORDER = 0x10;
static PdfiumNativeMethods()
{
if (PlatformCompat.System.CanUseWin32)
{
string libDir = Environment.Is64BitProcess ? "_win64" : "_win32";
var location = Assembly.GetExecutingAssembly().Location;
var coreDllDir = System.IO.Path.GetDirectoryName(location);
if (coreDllDir != null)
{
Win32.SetDllDirectory(System.IO.Path.Combine(coreDllDir, libDir));
}
}
}
[DllImport("pdfium.dll")]
public static extern IntPtr FPDFBitmap_Create(int width, int height, int alpha);
[DllImport("pdfium.dll")]
public static extern IntPtr FPDFBitmap_CreateEx(int width, int height, int format, IntPtr firstScan, int stride);
[DllImport("pdfium.dll")]
public static extern void FPDFBitmap_Destroy(IntPtr bitmap);
[DllImport("pdfium.dll")]
public static extern IntPtr FPDF_LoadDocument(string filePath, string password);
[DllImport("pdfium.dll")]
public static extern IntPtr FPDF_LoadMemDocument(IntPtr buffer, int size, string password);
[DllImport("pdfium.dll")]
public static extern int FPDF_GetPageCount(IntPtr document);
[DllImport("pdfium.dll")]
public static extern IntPtr FPDF_LoadPage(IntPtr document, int pageIndex);
[DllImport("pdfium.dll")]
public static extern double FPDF_GetPageWidth(IntPtr page);
[DllImport("pdfium.dll")]
public static extern double FPDF_GetPageHeight(IntPtr page);
[DllImport("pdfium.dll")]
public static extern void FPDF_RenderPageBitmap(IntPtr bitmap, IntPtr page, int startX, int startY, int sizeX, int sizeY, int rotate, int flags);
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NAPS2.Dependencies;
using NAPS2.Images.Storage;
using NAPS2.Scan;
namespace NAPS2.ImportExport.Pdf
{
public class PdfiumPdfRenderer : IPdfRenderer
{
private const int RENDER_FLAGS = PdfiumNativeMethods.FPDF_PRINTING | PdfiumNativeMethods.FPDF_REVERSE_BYTE_ORDER;
public IEnumerable<IImage> Render(string path)
{
// TODO: Maybe allow this to be configured
int dpi = ScanDpi.Dpi300.ToIntDpi();
var doc = PdfiumNativeMethods.FPDF_LoadDocument(path, null);
var pageCount = PdfiumNativeMethods.FPDF_GetPageCount(doc);
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++)
{
var page = PdfiumNativeMethods.FPDF_LoadPage(doc, pageIndex);
var widthInInches = PdfiumNativeMethods.FPDF_GetPageWidth(page) * 72;
var heightInInches = PdfiumNativeMethods.FPDF_GetPageWidth(page) * 72;
int widthInPx = (int)Math.Round(widthInInches * dpi);
int heightInPx = (int)Math.Round(heightInInches * dpi);
// Cap the resolution to 10k pixels in each dimension
dpi = Math.Min(dpi, (int)(10000 / heightInInches));
dpi = Math.Min(dpi, (int)(10000 / widthInInches));
var bitmap = StorageManager.ImageFactory.FromDimensions(widthInPx, heightInPx, StoragePixelFormat.RGB24);
bitmap.SetResolution(dpi, dpi);
var bitmapData = bitmap.Lock(LockMode.ReadWrite, out var scan0, out var stride);
try
{
var pdfiumBitmap = PdfiumNativeMethods.FPDFBitmap_CreateEx(widthInPx, heightInPx, PdfiumNativeMethods.FPDFBitmap_BGR, scan0, stride);
PdfiumNativeMethods.FPDF_RenderPageBitmap(pdfiumBitmap, page, 0, 0, widthInPx, heightInPx, 0, RENDER_FLAGS);
yield return bitmap;
}
finally
{
bitmap.Unlock(bitmapData);
}
}
}
public void PromptToInstallIfNeeded(IComponentInstallPrompt componentInstallPrompt)
{
}
public void ThrowIfCantRender()
{
}
}
}

View File

@ -206,6 +206,8 @@
<Compile Include="ImportExport\Email\Mapi\IMapiWrapper.cs" />
<Compile Include="ImportExport\Email\Mapi\MapiWrapper.cs" />
<Compile Include="ImportExport\Pdf\GhostscriptManager.cs" />
<Compile Include="ImportExport\Pdf\PdfiumPdfRenderer.cs" />
<Compile Include="ImportExport\Pdf\PdfiumNativeMethods.cs" />
<Compile Include="Logging\EventParams.cs" />
<Compile Include="Logging\EventType.cs" />
<Compile Include="Logging\IEventLogger.cs" />