Question

I'm inserting a TIFF file into a PDF using PDFSharp. That process works fine, but it's leaving a lock on the TIFF file. The TIFF file is on a SMB share. I am using the WPF version because the GDI version does not support CMYK TIFFs.

var output = new PdfDocument();
var input = PdfReader.Open(template_path, PdfDocumentOpenMode.Import);

var page = input.Pages[0];
output.AddPage(page);
page = output.Pages[0];

var gfx = XGraphics.FromPdfPage(page);

var image = XImage.FromFile(tiff_path);

gfx.DrawImage(image, 500, 200, 400, 400);

output.Save(destination_path);
output.Close();

Update: Simply doing this leaves the TIFF locked. No document opened or XGraphics or anything.

 using (var image = XImage.FromFile(path))
 {}

Update: This works, and is what I am going with for now.

using (var fsImage = File.Open(tiffPath, FileMode.Open, FileAccess.Read, FileShare.None))
{
    var bitmapSource = new BitmapImage();
    bitmapSource.BeginInit();
    bitmapSource.StreamSource = fsImage;
    bitmapSource.EndInit();

    using (var image = XImage.FromBitmapSource(bitmapSource))
    {

    }
}

Indecently, this nasty piece of code works also :-)

using (var image = XImage.FromFile(tiffPath))
{

}
GC.Collect();
Was it helpful?

Solution

With WPF BitmapSource, there is no deterministic disposal of the underlying stream, so you can end up with locks for as long as there is a reference.

You --> XImage --> BitmapSource --> Stream

If you call dispose on the XImage, it will release its reference on the BitmapSource, which will allow it to be finalized when the GC feels like it.

You can control when the file is closed by providing stream in lieu of a path and closing it explicitly. Doing so prematurely will cause exceptions in BitmapSource, however, so be sure you are not using the BitmapSource after you close the stream.

using (var fsImage = File.Open(tiff_path, FileMode.Open, FileAccess.Read, FileShare.None))
{
    var output = new PdfDocument();
    var input = PdfReader.Open(template_path, PdfDocumentOpenMode.Import);

    var page = input.Pages[0];
    output.AddPage(page);
    page = output.Pages[0];

    var gfx = XGraphics.FromPdfPage(page);

    var bitmapSource = new BitmapImage();
    bitmapSource.BeginInit();
    bitmapSource.StreamSource = fsImage;
    bitmapSource.EndInit();
    using (var image = XImage.FromBitmapSource(bitmapSource))
    {
        gfx.DrawImage(image, 500, 200, 400, 400);
    }

    output.Save(destination_path);
    output.Close();
}

If your image is small enough, you could skip the stream and just use the BitmapCacheOption of OnLoad to close the source after opening, but this will cause the entire image to be loaded into memory.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top