using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Xps.Packaging;
using System.IO;
using System.Windows.Documents;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using System.Windows.Threading;
using System.Threading;
using System.IO.Packaging;
using System.Xml;
namespace CBR.Core.Helpers
{
internal enum ThumbnailQuality
{
Low = 3,
Medium = 2,
Good = 1
}
internal class XpsHelper
{
public MemoryStream GenerateThumbnailFromFirstPage(string xpsFilePath, XpsImageType imgType, ThumbnailQuality imgQuality = ThumbnailQuality.Medium)
{
try
{
BitmapEncoder bitmapEncoder = null;
XpsDocument xpsDocument = new XpsDocument(xpsFilePath, FileAccess.Read);
FixedDocumentSequence documentPageSequence = xpsDocument.GetFixedDocumentSequence();
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(xpsFilePath);
string fileExtension = string.Empty;
switch (imgType)
{
case XpsImageType.JpegImageType:
bitmapEncoder = new JpegBitmapEncoder();
break;
case XpsImageType.PngImageType:
bitmapEncoder = new PngBitmapEncoder();
break;
}
double imageQualityRatio = 1.0 / (double)imgQuality;
DocumentPage documentPage = documentPageSequence.DocumentPaginator.GetPage(0);
RenderTargetBitmap targetBitmap = new RenderTargetBitmap((int)(documentPage.Size.Width * imageQualityRatio),
(int)(documentPage.Size.Height * imageQualityRatio),
96.0 * imageQualityRatio,
96.0 * imageQualityRatio,
PixelFormats.Pbgra32);
targetBitmap.Render(documentPage.Visual);
bitmapEncoder.Frames.Add(BitmapFrame.Create(targetBitmap));
MemoryStream memoryStream = new MemoryStream();
bitmapEncoder.Save(memoryStream);
xpsDocument.Close();
return memoryStream;
}
catch (Exception err)
{
ExceptionHelper.Manage("XpsHelper:GenerateThumbnailFromFirstPage", err);
}
return null;
}
public BitmapImage GetXpsThumbnail(string xpsFilePath)
{
XpsDocument document = null;
BitmapImage thumbImage = null;
try
{
document = new XpsDocument(xpsFilePath, FileAccess.Read);
XpsThumbnail thumb = document.Thumbnail;
if (thumb != null)
{
using (Stream xpsThumbStream = thumb.GetStream())
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
thumbImage = new BitmapImage();
thumbImage.BeginInit();
thumbImage.DecodePixelWidth = 70;
thumbImage.CacheOption = BitmapCacheOption.OnLoad;
thumbImage.StreamSource = xpsThumbStream;
thumbImage.EndInit();
});
}
}
else
{
using (Stream xpsThumb = GenerateThumbnailFromFirstPage(xpsFilePath, XpsImageType.JpegImageType, ThumbnailQuality.Low))
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
thumbImage = new BitmapImage();
thumbImage.BeginInit();
thumbImage.DecodePixelWidth = 70;
thumbImage.CacheOption = BitmapCacheOption.OnLoad;
thumbImage.StreamSource = xpsThumb;
thumbImage.EndInit();
});
}
}
}
catch (Exception err)
{
ExceptionHelper.Manage("XpsHelper:GetXpsThumbnail", err);
}
finally
{
if (document != null)
document.Close();
}
return thumbImage;
}
public bool WriteDocument(List<byte[]> images, string file_out)
{
XpsDocument doc = null;
IXpsFixedDocumentSequenceWriter docSeqWriter = null;
IXpsFixedDocumentWriter docWriter = null;
try
{
// xps doc does not manage overwrite, so delete before if exist
if (File.Exists(file_out))
File.Delete(file_out);
// create the document
doc = new XpsDocument(file_out, FileAccess.ReadWrite, CompressionOption.NotCompressed);
// Create the document sequence
docSeqWriter = doc.AddFixedDocumentSequence();
// Create the document
docWriter = docSeqWriter.AddFixedDocument();
for (int i = 0; i < images.Count; ++i)
{
// Create the Page
IXpsFixedPageWriter pageWriter = docWriter.AddFixedPage();
// Get the XmlWriter
XmlWriter xmlWriter = pageWriter.XmlWriter;
//create the xps image resource
XpsImage xpsImage = pageWriter.AddImage(XpsImageType.JpegImageType);
using (Stream dstImageStream = xpsImage.GetStream())
{
dstImageStream.Write(images[i], 0, images[i].Length);
xpsImage.Commit();
}
//this is just to get the real WPF image size as WPF display units and not image pixel size !!
using (MemoryStream ms = new MemoryStream(images[i]))
{
BitmapImage myImage = new BitmapImage();
myImage.BeginInit();
myImage.CacheOption = BitmapCacheOption.OnLoad;
myImage.StreamSource = ms;
myImage.EndInit();
//write the page
WritePageContent(xmlWriter, xpsImage, myImage.Width, myImage.Height);
}
//with the first page, create the thumbnail of the xps document
if (i == 0)
{
XpsThumbnail thumb = doc.AddThumbnail(XpsImageType.JpegImageType);
using (MemoryStream ms = new MemoryStream(images[i]))
{
BitmapImage thumbImage = new BitmapImage();
thumbImage.BeginInit();
thumbImage.DecodePixelWidth = 256;
thumbImage.CacheOption = BitmapCacheOption.OnLoad;
thumbImage.StreamSource = ms;
thumbImage.EndInit();
using (Stream xpsThumbStream = thumb.GetStream())
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(thumbImage));
encoder.Save(xpsThumbStream);
}
}
thumb.Commit();
}
xmlWriter.Flush();
// Close the page
pageWriter.Commit();
}
return true;
}
catch (Exception err)
{
ExceptionHelper.Manage("PDFImagesConverter:ExtractPDFtoXPS", err);
return false;
}
finally
{
if (docWriter != null)
docWriter.Commit();
if (docSeqWriter != null)
docSeqWriter.Commit();
if (doc != null)
doc.Close();
}
}
/// <summary>
/// write the xaml for the page
/// </summary>
/// <param name="xmlWriter"></param>
/// <param name="res"></param>
/// <param name="wpfWidth"></param>
/// <param name="wpfHeight"></param>
private void WritePageContent(System.Xml.XmlWriter xmlWriter, XpsResource res, double wpfWidth, double wpfHeight)
{
try
{
xmlWriter.WriteStartElement("FixedPage");
xmlWriter.WriteAttributeString("xmlns", @"http://schemas.microsoft.com/xps/2005/06");
xmlWriter.WriteAttributeString("Width", "794");
xmlWriter.WriteAttributeString("Height", "1123");
xmlWriter.WriteAttributeString("xml:lang", "en-US");
xmlWriter.WriteStartElement("Canvas");
if (res is XpsImage)
{
xmlWriter.WriteStartElement("Path");
xmlWriter.WriteAttributeString("Data", "M 0,0 L 794,0 794,1123 0,1123 z");
xmlWriter.WriteStartElement("Path.Fill");
xmlWriter.WriteStartElement("ImageBrush");
xmlWriter.WriteAttributeString("ImageSource", res.Uri.ToString());
xmlWriter.WriteAttributeString("Viewbox", string.Format("0,0,{0},{1}",
System.Convert.ToInt32(wpfWidth), System.Convert.ToInt32(wpfHeight)));
xmlWriter.WriteAttributeString("ViewboxUnits", "Absolute");
xmlWriter.WriteAttributeString("Viewport", "0,0,794,1123");
xmlWriter.WriteAttributeString("ViewportUnits", "Absolute");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
}
catch (Exception err)
{
ExceptionHelper.Manage("PDFImagesConverter:WritePageContent", err);
}
}
/// <summary>
/// helper for stream copy
/// </summary>
/// <param name="srcStream"></param>
/// <param name="destStream"></param>
private void StreamCopy(Stream srcStream, Stream destStream)
{
byte[] buf = new byte[1024];
int read = 0;
while ((read = srcStream.Read(buf, 0, buf.Length)) > 0)
{
destStream.Write(buf, 0, read);
}
}
}
}