Page 1 of 1

Setting image size when databinding with content control

PostPosted: Thu Jul 06, 2017 11:35 pm
by fabiohast
Hi,

I'm using the opendope content control toolkit and docx4j to bind information in a custom XML to my word document. It has worked out great so far. But now I need to bind images. To do this I'm using a picture content control, then binding it to an xpath in the custom xml, and then filling that xml with a Base 64 encode of the image I want. My problem is that when i bind the image, it always resizes to whatever the picture content control size is in the document. What I want to know is if it is possible to specify the width and height of the image in the custom XML (like an attribute)? Or at the very least maintain the natural image size?

Re: Setting image size when databinding with content control

PostPosted: Fri Jul 07, 2017 10:42 pm
by jason
This isn't a complete answer to your question, but by way of background, please see https://github.com/plutext/docx4j/blob/ ... mages.docx

The other possibility is to bind escaped XHTML; you have some control over image size that way.

Re: Setting image size when databinding with content control

PostPosted: Sat Jul 08, 2017 2:11 am
by fabiohast
Thanks for the reply,

According to the link you sent me, it's possible to use a rich text content control to bind images as opposed to a picture content control. I´ve also read in other posts, that using rich text control over picture control is the prefered way for binding images. My question is, would that allow me to retain the original size of the picture, instead of forcing the picture to resize in order to fit the control?

Re: Setting image size when databinding with content control

PostPosted: Sun Jul 09, 2017 12:55 pm
by jason
The picture stuff uses the size settings contained in the XML, it just replaces the image, but read on...

In bind.xslt we have:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
<!-- docx4j 3.0.1.  Handle a rich text control which contains an image.
    Since this doesn't have a w:databinding, we can't just use mode="picture3"
   
    If the w:sdtContent contains an existing w:drawing/wp:inline/a:graphic ..
    reuse it, so any formatting thus configured is used.
    We'll just replace the rId.. -->
  <xsl:template match=" @*|node()" mode="picture3richtext">
        <xsl:param name="tag" select="/.."/>
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"  mode="picture3richtext">
                                <xsl:with-param name="tag" select="$tag"/>
            </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
 
 
  <xsl:template match="a:blip" mode="picture3richtext" priority="1">
        <xsl:param name="tag" select="/.."/>
        <a:blip r:embed="{java:org.docx4j.model.datastorage.BindingTraverserXSLT.xpathInjectImageRelId(
                                                                $wmlPackage,
                                                                $sourcePart,
                                                                $customXmlDataStorageParts,
                                                                $xPathsMap,
                                                                $tag )}" />

                                                               
<!--  if it was @r:link, it is now embedded -->
  </xsl:template>
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


and

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
                <xsl:when test="w:sdtPr/w:dataBinding and w:sdtPr/w:picture">
                        <!--  honour w:dataBinding -->
                       
                        <xsl:choose>
                                <xsl:when test="w:sdtContent//a:blip"><!-- docx4j 3.0 -->
                                       
                                        <xsl:copy>
                                             <xsl:copy-of select="w:sdtPr"/>
                                             
                                             <xsl:if test="w:stdEndPr">
                                                <xsl:copy-of select="w:sdtEndPr"/>
                                        </xsl:if>
               
                                            <xsl:apply-templates select="w:sdtContent" mode="picture3">
                                                <xsl:with-param name="sdtPr" select="w:sdtPr"/>
                                            </xsl:apply-templates>
                                             
                                        </xsl:copy>
                               
                                </xsl:when>
                                <xsl:otherwise>
                                        <!--  fallback to pre v3 approach -->
                                        <xsl:copy>
                                             <xsl:copy-of select="w:sdtPr"/>
                                             
                                             <xsl:if test="w:stdEndPr">
                                                <xsl:copy-of select="w:sdtEndPr"/>
                                        </xsl:if>
               
                                             
                                             <w:sdtContent>
                                                                        <xsl:copy-of
                                                                        select="java:org.docx4j.model.datastorage.BindingTraverserXSLT.xpathInjectImage(
                                                                                                $wmlPackage,
                                                                                                $sourcePart,
                                                                                                $customXmlDataStorageParts,
                                                                                                string(w:sdtPr/w:dataBinding/@w:storeItemID),
                                                                                                string(w:sdtPr/w:dataBinding/@w:xpath),
                                                                                                string(w:sdtPr/w:dataBinding/@w:prefixMappings),
                                                                                                $parent,
                                                                                                $child,
                                                                                                string(w:sdtContent//wp:extent[1]/@cx),
                                                                                                string(w:sdtContent//wp:extent[1]/@cy))" />

                                             </w:sdtContent>
                                        </xsl:copy>
                               
                                </xsl:otherwise>
                        </xsl:choose>
                </xsl:when>
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.4



For the picture content control case, BindingTraverserXSLT's xpathInjectImage will use the cx, cy values found in the pre-existing image xml, unless they are 0. If 0, docx4j will work out the native image size. So you ought to be able to get this to happen, by editing those values to be 0.

For the rich text case, the image is replaced and that's all. No sizing magic.

As mentioned in my earlier reply, consider instead binding escaped XHTML containing a image. That uses https://github.com/plutext/docx4j-Impor ... fault.java which gets the image size this way: https://github.com/plutext/docx4j-Impor ... java#L1601

Re: Setting image size when databinding with content control

PostPosted: Tue Jul 11, 2017 1:33 am
by fabiohast
Regarding the first approach it didn't work for me. I edited my word document to have a picture content control with zero height and width to achieve this:

Code: Select all
<wp:extent cx="0" cy="0"/>


But when docx4j replaces the image, it still doesn't change the size, which means I end up with an image with zero height and width.

I'll take a look into the escaped XHTML binding then thanks for the help.