Search code examples
c#wpfxamlxps

How to embed JPEG images in XAML generated XPS?


I'm generating an XPS file on the fly using the XpsDocument class. In my XAML template I embed a JPEG image in an Image container. However, the embedded images in the resulting XPS are always PNG images - resulting in a very large files for certain types of images.

It seems the document writer interprets the rendered images as bitmaps and then saves them as PNG.

Here's the code that produces the XPS:

void ConvertToXps(IEnumerable<FixedDocument> fixedDocuments, Stream outputStream)
{
    var package = Package.Open(outputStream, FileMode.Create);
    var xpsDoc = new XpsDocument(package, CompressionOption.Normal);
    var xpsWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc);

    // XPS documents are built using fixed document sequences.
    var fixedDocSeq = new FixedDocumentSequence();

    // A4 = 210 x 297 mm = 8.267 x 11.692 inches = 793.632 * 1122.432 dots
    fixedDocSeq.DocumentPaginator.PageSize = new Size(793.632, 1122.432);

    foreach (var fixedDocument in fixedDocuments)
    {
        var docRef = new DocumentReference();
        docRef.BeginInit();
        docRef.SetDocument(fixedDocument);
        docRef.EndInit();
        ((IAddChild)fixedDocSeq).AddChild(docRef);
    }

    // Write out our fixed document to XPS.
    xpsWriter.Write(fixedDocSeq.DocumentPaginator);

    xpsDoc.Close();
    package.Close();
}

Q: How can I force my XAML rendered images to be saved as JPEG in the generated XPS?


Solution

  • I think you have to change the way you create your XPS document.

    var package = Package.Open(outputStream, FileMode.Create);
    var xpsDoc = new XpsDocument(package, CompressionOption.Normal);
    var xpsWriter = xpsDoc.AddFixedDocumentSequence();
    
    var fixedDocSeq = xpsDoc.GetFixedDocumentSequence();
    
    // A4 = 210 x 297 mm = 8.267 x 11.692 inches = 793.632 * 1122.432 dots
    fixedDocSeq.DocumentPaginator.PageSize = new Size(793.632, 1122.432);
    
    foreach (var fixedDocument in fixedDocuments)
    {
        var docWriter = xpsWriter.AddFixedDocument();
    
        var pageWriter = docWriter.AddFixedPage();
    
        var image = pageWriter.AddImage(XpsImageType.JpegImageType);
    
        Stream imageStream = image.GetStream();
    
        //Write your image to stream
    
        //Write the rest of your document based on the fixedDocument object
    }
    

    The key here is getting the IXpsFixedPageWriter with the docWriter.AddFixedPage();. This allows you to recreate your document, adding the images where you want them to be.

    Not sure you can edit the already created FixedDocument unfortunately.