Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix memory leak #16

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/PdfiumViewer.Demo/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace PdfiumViewer.Demo
{
Expand Down Expand Up @@ -279,11 +280,11 @@ private void SaveAsImages(string path)
for (var i = 0; i < Renderer.PageCount; i++)
{
var size = Renderer.Document.PageSizes[i];
var image = Renderer.Document.Render(i, (int)size.Width * 5, (int)size.Height * 5, 300, 300, false);
var imagew = Rendererw.Document.Render(i, 150, 200, 60, 60, false);

image.Save(Path.Combine(path, $"img{i}.png"));
imagew.Save(Path.Combine(path, $"img{i}.png"));
var image = Rendererw.Document.Render(i, 150, 200, 60, 60, false);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(image as BitmapSource));
using (var fileStream = new FileStream(Path.Combine(path, $"img{i}.png"), FileMode.Create))
encoder.Save(fileStream);
}
}
catch (Exception ex)
Expand Down
19 changes: 15 additions & 4 deletions src/PdfiumViewer/Core/IPdfMarker.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System.Windows.Media;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace PdfiumViewer.Core
{
Expand All @@ -12,11 +15,19 @@ public interface IPdfMarker
/// </summary>
int Page { get; }

object Tag { get; set; }

/// <summary>
/// Draw the marker.
/// </summary>
/// <param name="renderer">The PdfRenderer to draw the marker with.</param>
/// <param name="graphics">The Graphics to draw the marker with.</param>
void Draw(PdfRenderer renderer, DrawingContext graphics);
/// <param name="frame">The PdfFrame to draw the marker onto.</param>
IEnumerable<FrameworkElement> Draw(PdfFrame frame);

/// <summary>
/// Get the distance of the marker to a point on the PdfFrame
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
double GetDistance(Point point);
}
}
16 changes: 8 additions & 8 deletions src/PdfiumViewer/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using System.Drawing;
using System.Windows;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -185,17 +185,17 @@ public struct RECT
public int right;
public int bottom;

public RECT(Rectangle r)
public RECT(Rect r)
{
left = r.Left;
top = r.Top;
right = r.Right;
bottom = r.Bottom;
left = (int)r.Left;
top = (int)r.Top;
right = (int)r.Right;
bottom = (int)r.Bottom;
}

public Rectangle ToRectangle()
public Rect ToRectangle()
{
return new Rectangle(left, top, right - left, bottom - top);
return new Rect(left, top, right - left, bottom - top);
}
}

Expand Down
81 changes: 45 additions & 36 deletions src/PdfiumViewer/Core/PdfDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows;
using System.Drawing.Printing;
using System.IO;
using System.Windows.Interop;
using PdfiumViewer.Drawing;
using PdfiumViewer.Enums;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Runtime.InteropServices;

namespace PdfiumViewer.Core
{
Expand All @@ -19,7 +21,7 @@ public class PdfDocument : IPdfDocument
{
private bool _disposed;
private PdfFile _file;
private readonly List<SizeF> _pageSizes;
private readonly List<Size> _pageSizes;

/// <summary>
/// Initializes a new instance of the PdfDocument class with the provided path.
Expand Down Expand Up @@ -124,15 +126,15 @@ public static PdfDocument Load(Stream stream, string password)
/// <summary>
/// Size of each page in the PDF document.
/// </summary>
public IList<SizeF> PageSizes { get; private set; }
public IList<Size> PageSizes { get; private set; }

private PdfDocument(Stream stream, string password)
{
_file = new PdfFile(stream, password);
_pageSizes = new List<SizeF>(PageCount);
_pageSizes = new List<Size>(PageCount);
for (var i = 0; i < PageCount; i++)
_pageSizes.Add(new SizeF());
PageSizes = new ReadOnlyCollection<SizeF>(_pageSizes);
_pageSizes.Add(Size.Empty);
PageSizes = new ReadOnlyCollection<Size>(_pageSizes);
}

/// <summary>
Expand All @@ -144,7 +146,7 @@ private PdfDocument(Stream stream, string password)
/// <param name="dpiY">Vertical DPI.</param>
/// <param name="bounds">Bounds to render the page in.</param>
/// <param name="forPrinting">Render the page for printing.</param>
public void Render(int page, Graphics graphics, float dpiX, float dpiY, Rectangle bounds, bool forPrinting)
public void Render(int page, System.Drawing.Graphics graphics, float dpiX, float dpiY, Rect bounds, bool forPrinting)
{
Render(page, graphics, dpiX, dpiY, bounds, forPrinting ? PdfRenderFlags.ForPrinting : PdfRenderFlags.None);
}
Expand All @@ -158,7 +160,7 @@ public void Render(int page, Graphics graphics, float dpiX, float dpiY, Rectangl
/// <param name="dpiY">Vertical DPI.</param>
/// <param name="bounds">Bounds to render the page in.</param>
/// <param name="flags">Flags used to influence the rendering.</param>
public void Render(int page, Graphics graphics, float dpiX, float dpiY, Rectangle bounds, PdfRenderFlags flags)
public void Render(int page, System.Drawing.Graphics graphics, float dpiX, float dpiY, Rect bounds, PdfRenderFlags flags)
{
if (graphics == null)
throw new ArgumentNullException(nameof(graphics));
Expand All @@ -185,13 +187,13 @@ public void Render(int page, Graphics graphics, float dpiX, float dpiY, Rectangl
}

var point = new NativeMethods.POINT();
NativeMethods.SetViewportOrgEx(dc, bounds.X, bounds.Y, out point);
NativeMethods.SetViewportOrgEx(dc, (int)bounds.X, (int)bounds.Y, out point);

var success = _file.RenderPDFPageToDC(
page,
dc,
(int)dpiX, (int)dpiY,
0, 0, bounds.Width, bounds.Height,
0, 0, (int)bounds.Width, (int)bounds.Height,
FlagsToFPDFFlags(flags)
);

Expand All @@ -214,7 +216,7 @@ public void Render(int page, Graphics graphics, float dpiX, float dpiY, Rectangl
/// <param name="dpiY">Vertical DPI.</param>
/// <param name="forPrinting">Render the page for printing.</param>
/// <returns>The rendered image.</returns>
public Image Render(int page, float dpiX, float dpiY, bool forPrinting)
public ImageSource Render(int page, float dpiX, float dpiY, bool forPrinting)
{
var size = PageSizes[page];

Expand All @@ -229,7 +231,7 @@ public Image Render(int page, float dpiX, float dpiY, bool forPrinting)
/// <param name="dpiY">Vertical DPI.</param>
/// <param name="flags">Flags used to influence the rendering.</param>
/// <returns>The rendered image.</returns>
public Image Render(int page, float dpiX, float dpiY, PdfRenderFlags flags)
public ImageSource Render(int page, float dpiX, float dpiY, PdfRenderFlags flags)
{
var size = PageSizes[page];

Expand All @@ -246,7 +248,7 @@ public Image Render(int page, float dpiX, float dpiY, PdfRenderFlags flags)
/// <param name="dpiY">Vertical DPI.</param>
/// <param name="forPrinting">Render the page for printing.</param>
/// <returns>The rendered image.</returns>
public Image Render(int page, int width, int height, float dpiX, float dpiY, bool forPrinting)
public ImageSource Render(int page, int width, int height, float dpiX, float dpiY, bool forPrinting)
{
return Render(page, width, height, dpiX, dpiY, forPrinting ? PdfRenderFlags.ForPrinting : PdfRenderFlags.None);
}
Expand All @@ -261,11 +263,14 @@ public Image Render(int page, int width, int height, float dpiX, float dpiY, boo
/// <param name="dpiY">Vertical DPI.</param>
/// <param name="flags">Flags used to influence the rendering.</param>
/// <returns>The rendered image.</returns>
public Image Render(int page, int width, int height, float dpiX, float dpiY, PdfRenderFlags flags)
public ImageSource Render(int page, int width, int height, float dpiX, float dpiY, PdfRenderFlags flags)
{
return Render(page, width, height, dpiX, dpiY, 0, flags);
}

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);

/// <summary>
/// Renders a page of the PDF document to an image.
/// </summary>
Expand All @@ -277,7 +282,7 @@ public Image Render(int page, int width, int height, float dpiX, float dpiY, Pdf
/// <param name="rotate">Rotation.</param>
/// <param name="flags">Flags used to influence the rendering.</param>
/// <returns>The rendered image.</returns>
public Image Render(int page, int width, int height, float dpiX, float dpiY, PdfRotation rotate, PdfRenderFlags flags)
public ImageSource Render(int page, int width, int height, float dpiX, float dpiY, PdfRotation rotate, PdfRenderFlags flags)
{
if (_disposed)
throw new ObjectDisposedException(GetType().Name);
Expand All @@ -287,16 +292,13 @@ public Image Render(int page, int width, int height, float dpiX, float dpiY, Pdf
width = width * (int)dpiX / 72;
height = height * (int)dpiY / 72;
}

var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
bitmap.SetResolution(dpiX, dpiY);

var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, bitmap.PixelFormat);

// Create byte array to hold image data
byte[] imageData = new byte[width * height * 4]; // Assuming 32bpp ARGB format
GCHandle pinnedArray = GCHandle.Alloc(imageData, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
try
{
var handle = NativeMethods.FPDFBitmap_CreateEx(width, height, 4, data.Scan0, width * 4);

var handle = NativeMethods.FPDFBitmap_CreateEx(width, height, 4, pointer, width * 4);
try
{
var background = (flags & PdfRenderFlags.Transparent) == 0 ? 0xFFFFFFFF : 0x00FFFFFF;
Expand All @@ -320,13 +322,22 @@ public Image Render(int page, int width, int height, float dpiX, float dpiY, Pdf
{
NativeMethods.FPDFBitmap_Destroy(handle);
}
var bitmapSource = BitmapSource.Create(
width,
height,
dpiX,
dpiY,
PixelFormats.Bgra32,
null,
imageData,
width * 4);
bitmapSource.Freeze();
return bitmapSource;
}
finally
{
bitmap.UnlockBits(data);
pinnedArray.Free();
}

return bitmap;
}

private NativeMethods.FPDF FlagsToFPDFFlags(PdfRenderFlags flags)
Expand Down Expand Up @@ -440,7 +451,7 @@ public IList<PdfRectangle> GetTextBounds(PdfTextSpan textSpan)
/// <param name="page">The page number where the point is from.</param>
/// <param name="point">The point to convert.</param>
/// <returns>The converted point.</returns>
public PointF PointToPdf(int page, Point point)
public Point PointToPdf(int page, Point point)
{
return _file.PointToPdf(page, point);
}
Expand All @@ -451,7 +462,7 @@ public PointF PointToPdf(int page, Point point)
/// <param name="page">The page number where the point is from.</param>
/// <param name="point">The point to convert.</param>
/// <returns>The converted point.</returns>
public Point PointFromPdf(int page, PointF point)
public Point PointFromPdf(int page, Point point)
{
return _file.PointFromPdf(page, point);
}
Expand All @@ -462,7 +473,7 @@ public Point PointFromPdf(int page, PointF point)
/// <param name="page">The page where the rectangle is from.</param>
/// <param name="rect">The rectangle to convert.</param>
/// <returns>The converted rectangle.</returns>
public RectangleF RectangleToPdf(int page, Rectangle rect)
public Rect RectangleToPdf(int page, Rect rect)
{
return _file.RectangleToPdf(page, rect);
}
Expand All @@ -473,7 +484,7 @@ public RectangleF RectangleToPdf(int page, Rectangle rect)
/// <param name="page">The page where the rectangle is from.</param>
/// <param name="rect">The rectangle to convert.</param>
/// <returns>The converted rectangle.</returns>
public Rectangle RectangleFromPdf(int page, RectangleF rect)
public Rect RectangleFromPdf(int page, Rect rect)
{
return _file.RectangleFromPdf(page, rect);
}
Expand Down Expand Up @@ -512,11 +523,10 @@ public PrintDocument CreatePrintDocument(PdfPrintSettings settings)
/// Returns all links on the PDF page.
/// </summary>
/// <param name="page">The page to get the links for.</param>
/// <param name="size">The size of the page.</param>
/// <returns>A collection with the links on the page.</returns>
public PdfPageLinks GetPageLinks(int page, Size size)
public IReadOnlyList<PdfPageLink> GetPageLinks(int page)
{
return _file.GetPageLinks(page, size);
return _file.GetPageLinks(page);
}

/// <summary>
Expand Down Expand Up @@ -549,7 +559,7 @@ public PdfInformation GetInformation()
return _file.GetInformation();
}

public SizeF GetPageSize(int pageNo)
public Size GetPageSize(int pageNo)
{
if (_pageSizes.Count > pageNo && pageNo >= 0)
{
Expand All @@ -567,7 +577,6 @@ public SizeF GetPageSize(int pageNo)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
Expand Down
Loading