Re: [xep-support] Next CoolTool - Scale All to Fit

From: David Cramer <>
Date: Tue Mar 09 2010 - 08:24:52 PST

Kevin (and xep support),
Thank you for putting that together. It's good to have it as an option
and I'll look into incorporating it into our build and xslts the next
time I have a free afternoon.

While your test only takes 0.1 second to generate image.xep, that's for
a 4 KB file with ten images and on your hardware. Real documents are
larger, have more images, and may be built on more modest hardware.
Also, there's additional processing from adding the templates in
scale-all-to-fit.xsl. That's probably still ok in many cases, but the
milliseconds add up.

Thanks also for adding scale-down-to-fit to your marketing requirements
planning. I would much rather pay to upgrade xep so I can use
scale-down-to-fit than have to work these extra steps into my pipeline.


On 3/8/2010 1:06 PM, Kevin Brown wrote:
> As has been recently discussed in this forum, users need a way to scale down
> images to fit within a constrained space in both dimensions. We discussed a
> possible solution using the current technology and I have compiled that
> discussion and associated files into a single solution set. All is available
> for download here:
> Just sample XML and XSL without images:
> The whole package with images:
> (7MB)
> Sample output in various sizes:
> (7MB)
> (7MB)
> (7MB)
> The basic solution consists of running RenderX in a way to process only the
> images and gather information on the actual image size from the XEP
> Intermediate Format (XEPOUT). Then one can run RenderX again with the main
> style sheet and use that information when formatting the document. This can
> of course be done in a tool chain with two commands (instead of one) or
> through the API and passing params.
> We developed a simple text xml file that just had some paragraphs and
> various images throughout the document. These images vary by size and by
> type. In order to simplify things we added an attribute in our XML called
> scale-all-to-fit. If this attribute was set to 'true', we would process the
> image with this technique. Of course, you may do things differently. The
> basic idea is to be able to selectively process images because you may have
> some that you know the size and wish to process in a different way.
> Now, as we had shown, the actual dimensions of images are carried in the
> XEPOUT document. The trick here is to have no scaling happen for any reason
> so we create a simple XSL that only lays down images without any scaling.
> So, we set the page dimensions very large -- bigger than any expected image.
> If you look at the "process-images.xsl", it has:
> <fo:simple-page-master
> margin-top="0pt"
> margin-left="0pt"
> margin-bottom="0pt"
> margin-right="0pt"
> page-width="100in"
> page-height="100in"
> master-name="huge">
> Thus, a 100in x 100in page. We assumed that none of our images would be
> larger than this. Then we used a simple template:
> <xsl:template match="image[@scale-all-to-fit = 'true']">
> <fo:block line-height="0pt">
> <fo:external-graphic>
> <xsl:attribute name="src">
> <xsl:text>url('</xsl:text>
> <xsl:value-of select="@src"/>
> <xsl:text>')</xsl:text>
> </xsl:attribute>
> </fo:external-graphic>
> </fo:block>
> </xsl:template>
> This template outputs all images marked appropriately in natural size, no
> scaling.
> Running this against our sample XML would yield this in XEPOUT:
> <?xml version="1.0" encoding="UTF-8"?>
> <xep:document xmlns:xep="" producer="XEP
> CURRENT build 20100226" creator="Unknown" author="Unknown" title="Untitled">
> <xep:page width="7200000" height="7200000" page-number="1" page-id="1">
> <xep:gray-color gray="0.0"/>
> <xep:image
> src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/product_goodflakes.gif"
> type="image/gif" x-from="0" y-from="6835800" scale-x="1.0" scale-y="1.0"
> width="225600" height="364200" role="none"/>
> <xep:image
> src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/big-peng_00001.jpg"
> type="image/jpeg" x-from="0" y-from="4499800" scale-x="1.0" scale-y="1.0"
> width="2336000" height="2336000" role="none"/>
> <xep:image src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/circles.svg"
> type="image/svg+xml" x-from="0" y-from="4139800" scale-x="1.0" scale-y="1.0"
> width="360000" height="360000" role="none"/>
> <xep:image src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/gradients.svg"
> type="image/svg+xml" x-from="0" y-from="4079800" scale-x="1.0" scale-y="1.0"
> width="60000" height="60000" role="none"/>
> <xep:image src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/gradients2.svg"
> type="image/svg+xml" x-from="0" y-from="4019800" scale-x="1.0" scale-y="1.0"
> width="60000" height="60000" role="none"/>
> <xep:image src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/4morpap0.png"
> type="image/png" x-from="0" y-from="3094061" scale-x="1.0" scale-y="1.0"
> width="1068028" height="925739" role="none"/>
> <xep:image src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/clipimage.svg"
> type="image/svg+xml" x-from="0" y-from="2909809" scale-x="1.0" scale-y="1.0"
> width="340157" height="184252" role="none"/>
> <xep:image
> src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/blank-world-map.jpg"
> type="image/png" x-from="0" y-from="2737009" scale-x="1.0" scale-y="1.0"
> width="302400" height="172800" role="none"/>
> <xep:image src="file:/C:/Users/kbrown01/Desktop/Scale-to-fit/380009505.jpg"
> type="image/jpeg" x-from="0" y-from="2448259" scale-x="1.0" scale-y="1.0"
> width="768000" height="288750" role="none"/>
> </xep:page>
> </xep:document>
> As you can see, each image in here in an XML document with exact width and
> height values. These are in units of XEPOUT ... each unit is 1/1000th of a
> point (.001pt_). So the "big-peng_00001.jpg" above is 2336pt x 2336pt.
> Now, this XEPOUT document is used as a map within the main XSL. We developed
> a plug-in XSLT that with a template for scale-all-to-fit. The
> "scale-all-to-fit.xsl" takes in the fit-size and the XEPOUT file and then
> does some logic on what fits.
> Using the document() function and simple XSLT on the structure, one can
> extract real width and height for each image. Given a particular image
> "src":
> <xsl:variable name="image-width"
> select="($xepdoc//xep:image[contains(@src, $image-name)]/@width) div
> 1000"/>
> <xsl:variable name="image-height"
> select="($xepdoc//xep:image[contains(@src, $image-name)]/@height)
> div 1000"/>
> Then it is a matter of determining:
> 1) Does the image fit both width and height?
> 2) Does the image fit height and not width?
> 3) Does the image fit width and not height?
> 4) Does the image not fit width nor height?
> In case 4, the image fit and actual dimensions are evaluated to determine
> which ratio is larger and the dimension with the largest ratio of (actual
> size/fit size) is used for the scale to fit.
> Calling this template from the main XSL is easy. You do have to determine
> what your fit dimensions are. You can of course guess larger but in the
> simplest of cases you should know. In our simple document, we even added a
> keep for the caption that has a height (of course) and ensured the fit space
> would always keep the caption on the page with the image. The call to the
> template is:
> <xsl:template match="image[@scale-all-to-fit = 'true']">
> <fo:block line-height="0pt" text-align="center"
> background-color="silver">
> <xsl:call-template name="scale-image-to-fit">
> <xsl:with-param name="xepdoc" select="$xepdoc"/>
> <xsl:with-param name="fit-height">
> <xsl:value-of select="$page-height - $margin-top -
> $margin-bottom - $caption-height"/>
> </xsl:with-param>
> <xsl:with-param name="fit-width">
> <xsl:value-of select="$page-width - $margin-left -
> $margin-right"/>
> </xsl:with-param>
> <xsl:with-param name="image-name" select="@src"/>
> </xsl:call-template>
> </fo:block>
> <fo:block space-before="3pt" text-align="center"
> keep-with-previous.within-column="always" font-size="10pt"
> font-weight="bold" font-style="italic">
> <xsl:value-of select="@caption"/>
> </fo:block>
> </xsl:template>
> All of this was executed from a simple bat file. In the case of some users
> who are dynamically generating PDFs, certainly the XEPOUT file can be
> generated in memory and passed as a param to the second transformation. A
> simple .bat file for this would be:
> @echo off
> set CP=C:\Program Files (x86)\RenderX\XEP\lib\xep.jar;C:\Program Files
> (x86)\RenderX\XEP\lib\saxon.jar;C:\Program Files
> (x86)\RenderX\XEP\lib\xt.jar
> "C:\Program Files (x86)\Java\jre6\bin\java" -Xmx1024M -classpath "%CP%"
> com.renderx.xep.XSLDriver "-DCONFIG=C:\Program Files
> (x86)\RenderX\XEP\xep.xml" -xml %1 -xsl %2 -xep image.xep
> "C:\Program Files (x86)\Java\jre6\bin\java" -Xmx1024M -classpath "%CP%"
> com.renderx.xep.XSLDriver "-DCONFIG=C:\Program Files
> (x86)\RenderX\XEP\xep.xml" -xml %1 -xsl %3 -pdf
> del image.xep
> where:
> %1 is the XML file ("test.xml")
> %2 is "process-images.xsl"
> %3 is the main XSL file ("test.xsl")
> The XEPOUT file is generated automatically as "image.xep", used in the
> second transformation and then deleted. The "extra" first transformation to
> XEPOUT take 0.1 secs for this document.
> Hope this helps out some folks on their issues. We've added the
> scale-*-to-fit into the marketing requirements planning and we'll see where
> they fall into development and release. But as you can see from the
> examples, this can be implemented today to yield great results.
> Kevin Brown
> RenderX
> -------------------
> (*) To unsubscribe, send a message with words 'unsubscribe xep-support'
> in the body of the message to from the address
> you are subscribed from.
> (*) By using the Service, you expressly agree to these Terms of Service

(*) To unsubscribe, send a message with words 'unsubscribe xep-support'
in the body of the message to from the address
you are subscribed from.
(*) By using the Service, you expressly agree to these Terms of Service
Received on Tue Mar 9 08:56:04 2010

This archive was generated by hypermail 2.1.8 : Tue Mar 09 2010 - 08:56:11 PST