Search code examples
c#ms-wordopenxmlopenxml-sdk

OpenXml Force image fit in parent container


I'm parsing a piece of hmtl into a word document using the following code

//Need the following packages
//<package id="DocumentFormat.OpenXml" version="2.7.2" targetFramework="net471" />
//<package id = "HtmlToOpenXml.dll" version="2.0.1" targetFramework="net471" />

using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;

using DocumentFormat.OpenXml.Wordprocessing;
using HtmlToOpenXml;

namespace ConsoleAppHtmlParse
{
    class Program
    {
        static void Main(string[] args)
        {
            string fileName = @"C:\temp\myDoc.docx";

            using (WordprocessingDocument document = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
            {
                document.AddMainDocumentPart();
                document.MainDocumentPart.Document = new Document(new Body());
                HtmlConverter conveter = new HtmlConverter(document.MainDocumentPart);

                var compositeElements = conveter.Parse(Html);

                Paragraph p = compositeElements[0] as Paragraph;
                p.ParagraphProperties = new ParagraphProperties();
                p.ParagraphProperties.FrameProperties = new FrameProperties();
                p.ParagraphProperties.FrameProperties.Width = new StringValue("3200");

                document.MainDocumentPart.Document.Body.Append(compositeElements);
            }
        }

        const string Html = "<p>SomeText<img  src=\"data:image/png;base64,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\" alt=\"Screenshot_3\" />moretext</p>";
    }
}

The above code sample produces something like this:
enter image description here
I'd like to "shrink" the image to something like this:
enter image description here

Can I do this if I know the "parent" container size?

Thanks


Solution

  • Understanding the modifications for OpenXml:

    The w:drawing element has two parts to manage the image size

    1. wp:extent node, child of the wp:inline, it determines the extent of the area of the document that will contain the image. It is not helping us here.

    Note: It is essential for Libre Office

    extent

    1. spPr node is used to define the shape properties which contains xfrm node, which applies the transform to an object. It defines offset and extent.

    Note: It is essential for OpenXml - Google Documents, etc.

    inline extent

    I have written a program below with two modifications to your code.

    1. Define Page Width: Setting the PageSize and PageMargin: defines the available area that we need to fill with the image. In our case, the available area can be defined as below:

      Available Page Width = PageSize.Width - PageMargin.Left - PageMargin.Right

      // Define Constants for Page Width and Page Margin
      private const int PageWidth = 17000;
      private const int PageHeight = 10000;
      private const int PageMarginLeft = 1000;
      private const int PageMarginRight = 1000;
      private const int PageMarginTop = 1000;
      private const int PageMarginBottom = 1000;
      private const double DocumentSizePerPixel = 15;
      private const double EmuPerPixel = 9525;
      
      // Set Page Size and Page Margin so that we can place the image as desired.
      // Available Width = PageWidth - PageMarginLeft - PageMarginRight (= 17000 - 1000 - 1000 = 15000 for default values)
      var sectionProperties = new SectionProperties();
      sectionProperties.AppendChild(new PageSize { Width = PageWidth, Height = PageHeight });
      sectionProperties.AppendChild(new PageMargin { Left = PageMarginLeft, Bottom = PageMarginBottom, Top = PageMarginTop, Right = PageMarginRight });
      document.MainDocumentPart.Document.Body.AppendChild(sectionProperties);
      
    2. Update Image Width: Update the Extents with the updated value of width and height for the image

      1. Calculate the aspect ratio, useful in updating height for the image.

      2. Calculate the new width in Emu which is understood by word by using below

        15 width of Page = 1 width of image in pixel = 9525 EMUs per pixel

        Avalable page width = 15000 page width = 15000/ 15 pixels = 1000 pixels = 1000 * 9525 Emu = 9525000 Emu

      3. Update the width and height of the Page by using Extents in two separate places to be used by Google Documents and Libre Office, etc.

                 // Search for Extents used by the word present in Drawing > Inline > Extent
                var inlineEnumerable = p.ChildElements.Where(e => e is DocumentFormat.OpenXml.Wordprocessing.Run)
                    .Where(r => r.GetFirstChild<Drawing>() != null).Select(r => r.GetFirstChild<Drawing>())
                    .Where(r => r.GetFirstChild<Inline>() != null).Select(r => r.GetFirstChild<Inline>());
        
                // Update Visible Extent
                var inlineChildren = inlineEnumerable as Inline[] ?? inlineEnumerable.ToArray();
                foreach (var inlineChild in inlineChildren)
                {
                    var inlineElement = inlineChild.Extent;
                    UpdateExtent(inlineElement);
                }
        
                // Search for Extents used by the word present in Drawing > Inline > Graphic > GraphicData > Picture > ShapeProperties > Transform2D > Extents
                var extentsEnumerable = inlineChildren
                    .Where(r => r.GetFirstChild<Graphic>() != null).Select(d => d.GetFirstChild<Graphic>())
                    .Where(r => r.GetFirstChild<GraphicData>() != null).Select(r => r.GetFirstChild<GraphicData>())
                    .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>() != null)
                    .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>())
                    .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>() != null)
                    .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>())
                    .Where(r => r.GetFirstChild<Transform2D>() != null).Select(r => r.GetFirstChild<Transform2D>())
                    .Where(r => r.GetFirstChild<Extents>() != null).Select(r => r.GetFirstChild<Extents>());
        
                // Modify all images in Extents to the desired size here, to be stretched out on available page width
                foreach (var extents in extentsEnumerable)
                {
                    // Set Image Size: We calculate Aspect Ratio of the image and then calculate the width and update the height as per aspect ratio
                    var inlineElement = extents;
        
                    UpdateExtent(inlineElement);
                }
        

    Update Extent method to update the extent values:

        private static void UpdateExtent(dynamic inlineElement)
        {
            // Read Default Cx and Cy Values provided in Emu
            var extentCx = inlineElement.Cx;
            var extentCy = inlineElement.Cy;
    
            // Aspect ratio used to set image height after calculation of width
            double aspectRatioOfImage = (double)extentCy / extentCx;
    
            // We know 15 width of Page = 1 width of image in pixel = 9525 EMUs per pixel, and we convert document size to pixel and then to EMU
            // For Default Values Available page width = 15000 page width = 15000/ 15 pixels = 1000 pixels = 1000 * 9525 Emu = 9525000 Emu
            double newExtentCx = EmuPerPixel * ((PageWidth - PageMarginLeft - PageMarginRight) / DocumentSizePerPixel);
            // Maintain the Aspect Ratio for height
            double newExtentCy = aspectRatioOfImage * newExtentCx;
    
            // Update the values
            inlineElement.Cx = (long)Math.Round(newExtentCx);
            inlineElement.Cy = (long)Math.Round(newExtentCy);
        } 
    

    Full Program:

    namespace Solutions
    {
        using System;
        using System.Linq;
        using DocumentFormat.OpenXml;
        using DocumentFormat.OpenXml.Drawing;
        using DocumentFormat.OpenXml.Drawing.Wordprocessing;
        using DocumentFormat.OpenXml.Packaging;
        using DocumentFormat.OpenXml.Wordprocessing;
        using HtmlToOpenXml;
    
        using Paragraph = DocumentFormat.OpenXml.Wordprocessing.Paragraph;
    
        public class WordProcessorClass
        {
            const string Html = "<p>SomeText<img src=\"data:image/png;base64,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\" alt=\"Screenshot_3\" />moretext</p>";
    
            // Define Constants for Page Width and Page Margin
            private const int PageWidth = 17000;
            private const int PageHeight = 10000;
            private const int PageMarginLeft = 1000;
            private const int PageMarginRight = 1000;
            private const int PageMarginTop = 1000;
            private const int PageMarginBottom = 1000;
            private const double DocumentSizePerPixel = 15;
            private const double EmuPerPixel = 9525;
    
            public static void Main1()
            {
                string fileName = @"f:\myDoc.docx";
    
                using (WordprocessingDocument document = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
                {
                    document.AddMainDocumentPart();
                    document.MainDocumentPart.Document = new Document(new Body());
    
                    HtmlConverter converter = new HtmlConverter(document.MainDocumentPart);
                    var compositeElements = converter.Parse(Html);
                    var p = compositeElements[0] as Paragraph;
    
    
                    // Set Page Size and Page Margin so that we can place the image as desired.
                    // Available Width = PageWidth - PageMarginLeft - PageMarginRight (= 17000 - 1000 - 1000 = 15000 for default values)
                    var sectionProperties = new SectionProperties();
                    sectionProperties.AppendChild(new PageSize { Width = PageWidth, Height = PageHeight });
                    sectionProperties.AppendChild(new PageMargin { Left = PageMarginLeft, Bottom = PageMarginBottom, Top = PageMarginTop, Right = PageMarginRight });
                    document.MainDocumentPart.Document.Body.AppendChild(sectionProperties);
    
                    if (p != null)
                    {
                        // Search for Extents used by the word present in Drawing > Inline > Extent
                        var inlineEnumerable = p.ChildElements.Where(e => e is DocumentFormat.OpenXml.Wordprocessing.Run)
                            .Where(r => r.GetFirstChild<Drawing>() != null).Select(r => r.GetFirstChild<Drawing>())
                            .Where(r => r.GetFirstChild<Inline>() != null).Select(r => r.GetFirstChild<Inline>());
    
                        // Update Visible Extent
                        var inlineChildren = inlineEnumerable as Inline[] ?? inlineEnumerable.ToArray();
                        foreach (var inlineChild in inlineChildren)
                        {
                            var inlineElement = inlineChild.Extent;
                            UpdateExtent(inlineElement);
                        }
    
                        // Search for Extents used by the word present in Drawing > Inline > Graphic > GraphicData > Picture > ShapeProperties > Transform2D > Extents
                        var extentsEnumerable = inlineChildren
                            .Where(r => r.GetFirstChild<Graphic>() != null).Select(d => d.GetFirstChild<Graphic>())
                            .Where(r => r.GetFirstChild<GraphicData>() != null).Select(r => r.GetFirstChild<GraphicData>())
                            .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>() != null)
                            .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>())
                            .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>() != null)
                            .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>())
                            .Where(r => r.GetFirstChild<Transform2D>() != null).Select(r => r.GetFirstChild<Transform2D>())
                            .Where(r => r.GetFirstChild<Extents>() != null).Select(r => r.GetFirstChild<Extents>());
    
                        // Modify all images in Extents to the desired size here, to be stretched out on available page width
                        foreach (var extents in extentsEnumerable)
                        {
                            // Set Image Size: We calculate Aspect Ratio of the image and then calculate the width and update the height as per aspect ratio
                            var inlineElement = extents;
    
                            UpdateExtent(inlineElement);
                        }
                    }
    
                    document.MainDocumentPart.Document.Body.Append(compositeElements);
                }
            }
    
            private static void UpdateExtent(dynamic inlineElement)
            {
                // Read Default Cx and Cy Values provided in Emu
                var extentCx = inlineElement.Cx;
                var extentCy = inlineElement.Cy;
    
                // Aspect ratio used to set image height after calculation of width
                double aspectRatioOfImage = (double)extentCy / extentCx;
    
                // We know 15 width of Page = 1 width of image in pixel = 9525 EMUs per pixel, and we convert document size to pixel and then to EMU
                // For Default Values Available page width = 15000 page width = 15000/ 15 pixels = 1000 pixels = 1000 * 9525 Emu = 9525000 Emu
                double newExtentCx = EmuPerPixel * ((PageWidth - PageMarginLeft - PageMarginRight) / DocumentSizePerPixel);
                // Maintain the Aspect Ratio for height
                double newExtentCy = aspectRatioOfImage * newExtentCx;
    
                // Update the values
                inlineElement.Cx = (long)Math.Round(newExtentCx);
                inlineElement.Cy = (long)Math.Round(newExtentCy);
            }
        }
    }
    

    Output:

    Libre Office

    Libre Office Document

    Google Document

    Google Document

    Reference: Output Document