Page 1 of 1

A way to automatically scale all images in pdf?

Posted: Mon Jun 01, 2020 12:00 pm
by justyna_i
Hello,

is there any automatic way to scale all images throughout the dita bookmap into the same size in PDF print?

I have inherited dita structures that include images added by different people, different time, different resolution, different sizes. The result is that images throughout the whole pdf have different sizes.

Preferably some setting in XSLT customization that overrides each image own attributes?

P.S. All images are conkeyref-ed.

Re: A way to automatically scale all images in pdf?

Posted: Tue Jun 09, 2020 11:28 am
by Radu
Hi,

Sorry for the delay. Are you publishing to PDF using the default XSL-FO based publishing or Oxygen's specific CSS-based PDF publishing? For the latter you can impose the width directly from the CSS:

https://www.oxygenxml.com/doc/versions/ ... mages.html

For the former you would indeed need to perform some XSLT customizations:

https://www.oxygenxml.com/doc/versions/ ... utput.html

The XSLT stylesheet:

DITA-OT-DIR/plugins/org.dita.pdf2/xsl/fo/topic.xsl

has a template which matches any DITA image element:

Code: Select all

<xsl:template match="*[contains(@class,' topic/image ')]" name="image">
so you would need to override it in your XSLT customization.

Regards,
Radu

Re: A way to automatically scale all images in pdf?

Posted: Tue Jun 09, 2020 11:32 am
by justyna_i
Hi,

thank you for response,
I am using custom pdf plugin based on XSL-FO.

<xsl:template match="*[contains(@class,' topic/image ')]" name="image">

Do I need to create new attribute set for that?
Could you please help with code a bit more? - I am not that fluent in XSL-FO customizations yet.

Re: A way to automatically scale all images in pdf?

Posted: Tue Jun 09, 2020 11:55 am
by Radu
Hi,

There is another XSLT template in the same topic.xsl XSLT which looks more interesting:

Code: Select all

<xsl:template match="*" mode="placeImage">
If you copy that entire xsl template to your XSLT customization stylesheet, it has two places where it does something like:

Code: Select all

<xsl:if test="$height">
                <xsl:attribute name="content-height">
                <!--The following test was commented out because most people found the behavior
                 surprising.  It used to force images with a number specified for the dimensions
                 *but no units* to act as a measure of pixels, *if* you were printing at 72 DPI.
                 Uncomment if you really want it. -->
                    <xsl:choose>
                      <!--xsl:when test="not(string(number($height)) = 'NaN')">
                        <xsl:value-of select="concat($height div 72,'in')"/>
                      </xsl:when-->
                      <xsl:when test="not(string(number($height)) = 'NaN')">
                        <xsl:value-of select="concat($height, 'px')"/>
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:value-of select="$height"/>
                      </xsl:otherwise>
                    </xsl:choose>
                </xsl:attribute>
            </xsl:if>
            <!--Setting image width if defined-->
            <xsl:if test="$width">
                <xsl:attribute name="content-width">
                    <xsl:choose>
                      <!--xsl:when test="not(string(number($width)) = 'NaN')">
                        <xsl:value-of select="concat($width div 72,'in')"/>
                      </xsl:when-->
                      <xsl:when test="not(string(number($width)) = 'NaN')">
                        <xsl:value-of select="concat($width, 'px')"/>
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:value-of select="$width"/>
                      </xsl:otherwise>
                    </xsl:choose>
                </xsl:attribute>
            </xsl:if>
            <xsl:if test="not($width) and not($height) and $scale">
                <xsl:attribute name="content-width">
                    <xsl:value-of select="concat($scale,'%')"/>
                </xsl:attribute>
            </xsl:if>
In those places maybe instead of relying on the @scale, @width and @height attributes defined in the DITA content you can set your own XSl-FO content-width attribute value.
But I'm not sure how scalable this is, are you sure that you can find that magic width for which all images will look good in the PDF, no matter how small or large they were originally? For example we sometimes use very small images to represent button icons in the PDF, those images need to remain small in the PDF, so they should not be scaled up forcefully.

Regards,
Radu

Re: A way to automatically scale all images in pdf?

Posted: Tue Jun 30, 2020 1:56 pm
by justyna_i
You are absolutely right, there are also smaller icons in the pdf and I dont want them scaled.

As a solution, we run a batch task on all images, that scaled them to the same size and resolution and it worked.

Thank you for your help!

Re: A way to automatically scale all images in pdf?

Posted: Mon Nov 29, 2021 6:20 pm
by Marta Bartnicka
Hello! I have been using this attribute set successfully with DITA files:
<xsl:attribute name="content-width">scale-to-fit</xsl:attribute>
<xsl:attribute name="content-height">100%</xsl:attribute>
<xsl:attribute name="width">100%</xsl:attribute>
<xsl:attribute name="scaling">uniform</xsl:attribute>

However, now I am stuck when Markdown files with images are added to a ditamap, because the images have no placement information in the intermediate DITA files. The only distinguishing factor is whether an image has title - this will wrap an image into a fig.
What I'd need, is a set of attributes that would still do the job, i.e. scale everything down to page size without messing with inline images (= without taking them to a separate line).

<xsl:attribute name="content-width">scale-to-fit</xsl:attribute>

<!-- This attribute gets big image scaled down to page size but puts small images in a new line -->
<xsl:attribute name="content-height">100%</xsl:attribute>

<!-- This attribute gets small image inline but big image not scaled down -->
<xsl:attribute name="width">100%</xsl:attribute>

<xsl:attribute name="scaling">uniform</xsl:attribute>

Has anybody come with an universal attributes set that'd work for both small and big images? :)

Re: A way to automatically scale all images in pdf?

Posted: Thu Dec 02, 2021 2:42 pm
by Radu
Hi Marta,

So when you have images between paragraphs in the Markdown content they get converted to DITA images but without the placement=break attribute set on them?
In the XSLT stylesheet:

OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT3.x/plugins/org.dita.pdf2/xsl/fo/topic.xsl

there is an XSLT template which matches and converts to xsl-fo any image:

Code: Select all

 <xsl:template match="*[contains(@class,' topic/image ')]" name="image">
maybe you can overwrite this template in your PDF customization, the template has a condition where it decides to display the image using the block attributes:

Code: Select all

 <xsl:when test="@placement = 'break'">
                    <fo:block xsl:use-attribute-sets="image__block">
maybe you can change it to treat any image which is not inside a paragraph as being a block:

Code: Select all

<xsl:when test="not(ancestor::p)">
                    <fo:block xsl:use-attribute-sets="image__block">
            
or go the other way around and consider all images placed directly inside the topic body as being block images:

Code: Select all

 <xsl:when test="@placement = 'break' or parent::body">
                    <fo:block xsl:use-attribute-sets="image__block">
As in the template you have access to the nodes and can run XPaths you have more flexibility than when changing the attribute set definitions.

Regards,
Radu

Re: A way to automatically scale all images in pdf?

Posted: Mon Dec 13, 2021 4:03 pm
by Marta Bartnicka
Hi Radu! I like your solution, it's more elegant and extensible to first define placement and then have attributes assigned to the placement. The only hard part I find is that when I transform Markdown to DITA (with dita-ot 3.5 still), the intermediate DITA not only has no placement assigned to images (like I believed it should https://www.dita-ot.org/dev/topics/mark ... ce__images), but also all images are covered within a <p>, no matter how I placed them in Markdown, so there's no way to distinguish them in this way... One and only differentiator is that images that had title in Markdown, are wrapped in a <fig> in the intermediate DITA, so I can at least do that:
<xsl:when test="@placement = 'break' or parent::fig">
<fo:block xsl:use-attribute-sets="image__block">
Still, no solution for large images with no title...

Re: A way to automatically scale all images in pdf?

Posted: Mon Dec 13, 2021 4:38 pm
by Radu
Hi Marta,

Let's try to discuss over a small Markdown sample:

Code: Select all

# Header 1

This is an image:

![](../dita/flowers/images/Chrysanthemums.jpg)
when this gets published, does the temporary DITA topic have a <p> element around the image reference?

Regards,
Radu

Re: A way to automatically scale all images in pdf?

Posted: Mon Dec 13, 2021 9:23 pm
by Marta Bartnicka
Thanks!!! I forgot the Golden Rule of Markdown: if it doesn't work as expected, try adding an empty line.
With an empty line between the paragraph of text (This is an image:) and an image definition (![](../dita/flowers/images/Chrysanthemums.jpg)) I got the temporary DITA topic have NO <p> element around the image reference and also a placement="break" assigned to the image :)))
So now I can rely on the not(ancestor::p) or just placement attribute. I need to try this with different images, but I'm closer now.