Paul Taylor
Paul Taylor

Reputation: 5751

Inserted image not displayed in OpenXml created Word document

I'm trying to insert a signature image in a Word document created by a standard-letter generating application. I am using code adapted from various examples found on the web (see below). The application inserts the image, and the space in the document occupied by it is correct, but the image itself is not displayed.

I have tried it with both .png and .jpg images, but neither work; it doesn't appear to be a problem with the image itself.

I have examined the document using the OpenXml SDK Tool, which shows that the image is correctly embedded and encoded as a Base64 data string.

The problem that the SDK Tool does identify is that, compared to a document in which an image is manually inserted (and is correctly displayed), the pic:pic element in the document is rendered with the wrong namespace (a:pic) and it and all child controls are rendered as OpenXmlUnknownElement (see screenshot below).

Can anyone please tell me what is causing the incorrect namespace / element, and how to fix the problem?

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Drawing;
using System.Drawing.Imaging;
...
using A = DocumentFormat.OpenXml.Drawing;
using A14 = DocumentFormat.OpenXml.Office2010.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
using WP = DocumentFormat.OpenXml.Wordprocessing;


    private void ReplacePlaceholderWithImage(MainDocumentPart mainDocumentPart, OpenXmlElement placeholder, string imagePath)
    {
        if (placeholder != null)
        {
            ImagePart ip = AddImagePart(mainDocumentPart, imagePath);
            string relationshipId = mainDocumentPart.GetIdOfPart(ip);
            var drawing = GetDrawing(relationshipId, imagePath);

            placeholder.InsertAfterSelf(new WP.Paragraph(new WP.Run(drawing)));
            placeholder.Remove();

            Console.WriteLine("Picture inserted into picture content control successfully");
        }
    }

    private ImagePart AddImagePart(MainDocumentPart mainDocumentPart, string imagePath)
    {
        var partType = GetPartTypeForImage(imagePath);
        ImagePart ip = mainDocumentPart.AddImagePart(partType);
        using (FileStream fileStream = File.Open(imagePath, FileMode.Open))
        {
            ip.FeedData(fileStream);
        }
        return ip;
    }

    private OpenXmlElement GetDrawing(string relationshipId, string imagePath)
    {
        //calculate dimensions
        var size = GetImageDimensions(imagePath);

        // Define the reference of the image.
        return 
            new Drawing(
                new DW.Inline(
                    new DW.Extent()
                    {
                        Cx = size.Width,
                        Cy = size.Height
                    },
                    new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
                    new DW.DocProperties() { Id = 1U, Name = "Picture 1" },
                    new DW.NonVisualGraphicFrameDrawingProperties(new A.GraphicFrameLocks() { NoChangeAspect = true, NoResize = true, NoSelection = true }),
                    new A.Graphic(new A.GraphicData(new PIC.Picture(
                                new PIC.NonVisualPictureProperties(
                                    new PIC.NonVisualDrawingProperties()
                                    {
                                        Id = 0U,
                                        Name = Path.GetFileName(imagePath)
                                    },
                                    new PIC.NonVisualPictureDrawingProperties()),
                                new A.BlipFill(
                                    new A.Blip(
                                        new A.BlipExtensionList(
                                            new A.BlipExtension()
                                            {
                                                Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}"
                                            }))
                                    {
                                        Embed = relationshipId,
                                        CompressionState = A.BlipCompressionValues.Print
                                    },
                                    new A.Stretch(new A.FillRectangle())),
                                new A.ShapeProperties(
                                    new A.Transform2D(new A.Offset() { X = 0L, Y = 0L }, new A.Extents() { Cx = size.Width, Cy = size.Width }),
                                    new A.PresetGeometry(new A.AdjustValueList()) { Preset = A.ShapeTypeValues.Rectangle })))
                    {
                        Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture"
                    }))
                {
                    DistanceFromTop = 0U,
                    DistanceFromBottom = 0U,
                    DistanceFromLeft = 0U,
                    DistanceFromRight = 0U,
                    EditId = "50D07946"
                });
    }

    private ImagePartType GetPartTypeForImage(string imagePath)
    {
        var img = GetImage(imagePath);
        if (img.RawFormat.Equals(ImageFormat.Gif))
        {
            return ImagePartType.Gif;
        }
        else if (img.RawFormat.Equals(ImageFormat.Png))
        {
            return ImagePartType.Png;
        }
        else if (img.RawFormat.Equals(ImageFormat.Jpeg))
        {
            return ImagePartType.Jpeg;
        }
        else
        {
            throw new ApplicationException("Unexpected image type");
        }
    }

OpenXml SDK Tool view of document

Upvotes: 0

Views: 1393

Answers (2)

Gavin Coates
Gavin Coates

Reputation: 1425

Watch your namespaces! I'm guessing you've copied from the same source as I did (which I'm sure was the Microsoft documentation), however the namespaces appear to be wrong in it for the following two properties:

A.BlipFill -> PIC.BlipFill

A.ShapeProperties -> PIC.ShapeProperties

Full code below:

var element = new Drawing(
            new DW.Inline(
                new DW.Extent()
                {
                    Cx = 5657850L,
                    Cy = 3771900L
                },
                new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
                new DW.DocProperties() { Id = 1U, Name = "Picture 1" },
                new DW.NonVisualGraphicFrameDrawingProperties(new A.GraphicFrameLocks() { NoChangeAspect = true, NoResize = true, NoSelection = true }),
                new A.Graphic(new A.GraphicData(new PIC.Picture(
                            new PIC.NonVisualPictureProperties(
                                new PIC.NonVisualDrawingProperties()
                                {
                                    Id = 0U,
                                    Name = "image.png"
                                },
                                new PIC.NonVisualPictureDrawingProperties()),
                            new PIC.BlipFill(
                                new A.Blip(
                                    new A.BlipExtensionList(
                                        new A.BlipExtension()
                                        {
                                            Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}"
                                        }))
                                {
                                    Embed = relationshipId,
                                    CompressionState = A.BlipCompressionValues.Print
                                },
                                new A.Stretch(new A.FillRectangle())),
                            new PIC.ShapeProperties(
                                new A.Transform2D(new A.Offset() { X = 0L, Y = 0L }, new A.Extents() { Cx = 5657850L, Cy = 3771900L }),
                                new A.PresetGeometry(new A.AdjustValueList()) { Preset = A.ShapeTypeValues.Rectangle })))
                {
                    Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture"
                }))
            {
                DistanceFromTop = 0U,
                DistanceFromBottom = 0U,
                DistanceFromLeft = 0U,
                DistanceFromRight = 0U,
                EditId = "50D07946"
            });

Upvotes: 1

Nick Hoàng
Nick Hoàng

Reputation: 437

this issue stressed me up some hours and finally I found the reason. That's because the Drawing element Id need to be unique, you can't fix the ID like this

new DW.DocProperties() { Id = 1U, Name = "Picture 1" }

In my case, I have this function to set alt text and update the Id as well:

    private static HashSet<uint> _drawingElementIds = new HashSet<uint>();
    public static void SetPictureAltText(OpenXmlElement imageContainer, string altText)
    {
        var docPro = imageContainer.Descendants<DocProperties>().FirstOrDefault();
        if (docPro != null)
        {                
            //Make sure new image has unique ID, otherwise some images won't display
            var newId = (uint)new Random().Next(10, 10000);
            while (_drawingElementIds.Contains(newId))
            {
                newId = (uint)new Random().Next(10, 10000);
            }
            _drawingElementIds.Add(newId);

            docPro.Id = new UInt32Value(newId);
            docPro.Description = altText;
        }            
    }

Cheers, Nick

Upvotes: 1

Related Questions