I've been working on a project recently that had a requirement to do a tiff to pdf conversion on the fly, and serve these pdf's over the web. The added wrinkle was that these tiff files were stored in a database - so I wasn't going to reading or writing from the filesystem. This isn't a huge problem, but it did throw 90% of the examples out of the window!
I opted to use PdfSharp to do the conversion this - it's a really great open source library and did exactly what I needed.
So here we go:
snippet 1:
byte[] bytes = GetMyByteData();
using (MemoryStream memoryStream = new MemoryStream(bytes))
{
memoryStream.Position = 0;
memoryStream.Write(bytes, 0, bytes.Length);
System.Drawing.Image image = System.Drawing.Image.FromStream(memoryStream, true, true);
//This is where the next code goes!!
}
To start with I retrieved my data from the database into a byte array, wrote it into a memory stream object and finally created an Image object from the memory stream. Next onto creating the pdf document:
snippet 2:
PdfDocument doc = new PdfDocument(); XGraphics xgr; PdfPage page = new PdfPage(); doc.Pages.Add(page); xgr = XGraphics.FromPdfPage(page); XImage ximg = XImage.FromGdiPlusImage(image); xgr.DrawImage(ximg, 0, 0);
As you can see from the code, this is where PdfSharp comes into play (I opted for the GDI+ version) - creating a PdfDocument, XGraphics object, PdfPage and loading the image into page. I guess the real magic here when using the XImage.FromGdiPlusImage method to load the in memory image file into a pdf writeable object.
Finally was writing this back to the response stream (in ASP.NET obviously!):
snippet 3:
using (MemoryStream responseStream = new MemoryStream())
{
doc.Save(responseStream, false);
responseStream.Position = 0;
context.Response.ClearContent();
context.Response.ClearHeaders();
context.Response.BufferOutput = true;
context.Response.ContentType = "application/pdf";
context.Response.AddHeader("content-disposition", "inline;filename=mypdf.pdf");
responseStream.CopyTo(context.Response.OutputStream);
context.Response.Flush();
context.Response.Close();
context.Response.End();
}
doc.Close();
I wont go into too much detail about this, its pretty straight forward stuff. For me the 2 things really worth mentioning is the doc.Save() method which saves the pdf to a new memory stream, and the responseStream.CopyTo method which copies one stream to another (new to .net 4 I think!).
This all worked fine but there was one further complication - the TIFFs might be multi-page. In those examples the pdf would only ever contain the first page. To overcome this I had to loop over the page frames and add a new pdf page for each one. This replaces snippet 2 with the following:
snippet 2(v2):
PdfDocument doc = new PdfDocument();
XGraphics xgr;
int count = image.GetFrameCount(FrameDimension.Page);
for (int pageNum = 0; pageNum < count; pageNum++) { image.SelectActiveFrame(FrameDimension.Page, pageNum); PdfPage page = new PdfPage(); doc.Pages.Add(page); xgr = XGraphics.FromPdfPage(page); XImage ximg = XImage.FromGdiPlusImage(image); xgr.DrawImage(ximg, 0, 0); }
I was pleasantly surprised with how straight forward this was to achieve, and in particular how quickly it all worked.
Matt
source : http://www.codenutz.com/2011/10/creating-multi-page-pdf-from-tiff-tiff.html
