Search code examples
javaimageapache-fop

Apache FOP, scale image down to exact size in millimeters


I'm trying to scale an image down to exact specifications, 87mm x 10mm, but I'm not getting it down to the right size.

I'm using Apache FOP 2.0, here's my fop.xconf:

<fop version="1.0">

<strict-configuration>true</strict-configuration>
<strict-validation>true</strict-validation>
<base>./</base>
<font-base>./</font-base>

<source-resolution>72</source-resolution>
<target-resolution>72</target-resolution>

<default-page-settings height="11in" width="8.26in"/>

</fop>

Here's the snippet that is supposed to display the image, it displays the image, but never getting down to the size I've specified.

 <fo:flow flow-name="xsl-region-body">
    <fo:block font-size="3pt" text-align="center" font-weight="bold">
        <fo:external-graphic src="data:image/png;base64, {{barcodeimage}}" content-width="87mm" width="100%" content-height="10mm" scaling="non-uniform"/>
    </fo:block>
    <fo:block font-size="8pt" text-align="center" font-weight="bold">
        {{barcodetext}}
    </fo:block>
</fo:flow>

Switching to height and width and the image doesn't resize at all:

<fo:external-graphic src="data:image/png;base64, {{barcodeimage}}" width="87mm" height="10mm" scaling="non-uniform"/>

I've tried playing around with pt instead of mm with no success, tried switching to px by using this formula px = mm * dpi / 25.4 and still no luck.

Using em instead of mm and content-width instead of width, the image shrinks, but I have no idea, how to convert from mm to em units.

What I need is for a large image to be displayed scaled down to 87mm width and 10mm height, what is the correct way to do it?

Update: It seems the image displays correctly, the page size is incorrect, here's a screenshot taken in Okular PDF Viewer:

screenshot

And this is my full page XML:

<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

    <fo:layout-master-set>
        <fo:simple-page-master master-name="simple" page-height="29.7cm" page-width="21cm" margin="1cm">
            <fo:region-body margin-top="18mm"/>
            <fo:region-before extent="0"/>
            <fo:region-after extent="0"/>
        </fo:simple-page-master>
    </fo:layout-master-set>

    <fo:page-sequence master-reference="simple">

        <!-- Page Header Goes Here -->
        <fo:static-content flow-name="xsl-region-before">
            <fo:block font-size="8pt" text-align="center" font-weight="normal">
                Test BarCode
            </fo:block>
        </fo:static-content>

        <!-- Page Footer Goes Here -->
        <fo:static-content flow-name="xsl-region-after">
            <fo:block font-size="8pt" text-align="center">
                Page
                <fo:page-number/>
            </fo:block>
        </fo:static-content>

        <!-- Page Body Goes Here -->
        <fo:flow flow-name="xsl-region-body">

             <fo:block text-align="center">
                <fo:external-graphic src="data:image/png;base64, barcodeimage" content-width="87mm" content-height="10mm" scaling="non-uniform"/>
             </fo:block>
             <fo:block font-size="5pt" text-align="center" font-weight="normal">
                barcodetext
             </fo:block>
        </fo:flow>

    </fo:page-sequence>
</fo:root>

Solution

  • You should be able to achieve what you need using content-width, content-height and scaling:

    <fo:external-graphic src="data:image/png;base64, {{barcodeimage}}" 
        content-width="87mm" content-height="10mm" 
        scaling="non-uniform"/>
    

    To summarize the role of the different properties:

    • content-width and content-height control the image size
    • scaling controls the image aspect ratio (either preserved or modified to fit the desired image size)
    • width and height control the viewport size through which the image is seen; it could be bigger than the image size, thus leaving some empty gap, or smaller than the image size
    • overflow states what to do if the viewport size is smaller than the image size

    (disclosure: I'm a FOP developer, though not very active lately)