Trying to print a custom image on Cover Page in PDF

Post here questions and problems related to editing and publishing DITA content.
Tinmen
Posts: 21
Joined: Wed Jun 28, 2023 11:49 pm

Trying to print a custom image on Cover Page in PDF

Post by Tinmen »

I am curious why the following XML and XSLT codes don't work.

XML in ditamap:

Code: Select all

<bookmeta>
<data name="cover-art1.png"/> <!-- The tech writer will change this value (path and file name) depending on their specific cover art -->
</bookmeta>
XSLT in front-matter.xsl

Code: Select all

<fo:block text-align="center" width="100%">
<xsl:value-of select="//bookmeta/data/@name"/> <!-- Temporary: prints the value in the PDF for my testing and error checking -->
 <fo:external-graphic src="url('{//bookmeta/data/@name}')"/>
</fo:block>
PDF Output:
cover-art1.png in text from the code above but no external graphic image appears.

Error Output:
Engine name: FOP
Severity: error
Description: Image not found. URI: cover-art1.png. (See position 1:16922)
Radu
Posts: 9059
Joined: Fri Jul 09, 2004 5:18 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Radu »

Hi,

This XPath "//bookmeta/data/@name" returns a relative file path. It should be made absolute relative to the current processed file.
You could try to use something like this "resolve-uri((//bookmeta/data/@name)[1])". Again you can use xsl:messages to print the value of the resolve-uri method to see that it is correct.
When the XSLT is applied on the merged DITA Map, the merged DITA Map is no longer in the original input folder, it is located in a transformation temporary files folder. So that relative reference to "cover-art1.png" will resolve in the same temporary files folder. But the publishing engine does not automatically copy images referenced using "data name="cover-art1.png"" to the temporary files folder.
I suggest you could encode this information in the DITA Map like this:

Code: Select all

  <data name="coverImage" keyref="coverImage"/>
  <keydef keys="coverImage" href="cover-art1.png" format="png"/>
and your XPath could change to something like:

Code: Select all

"resolve-uri((//bookmeta/data[@name='coverImage']/@href)[1])"
as the @keyref will get resolved in the merged XML document. In this way you are also more precise, you do not just match any data element, you match a data element with a specific name and take its href value.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Tinmen
Posts: 21
Joined: Wed Jun 28, 2023 11:49 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Tinmen »

Hi Radu:
TMK, <keydef> is not allowed inside of the <bookmeta> elements in the ditamap.

Regards
Tinmen
Radu
Posts: 9059
Joined: Fri Jul 09, 2004 5:18 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Radu »

Hi Tinmen,

Right, what we would do for the Oxygen user's guide would be to place in the frontmatter element a mapref to a keys DITA Map:
https://github.com/oxygenxml/userguide/ ... al.ditamap

Code: Select all

<mapref href="maps/keydefs.ditamap"/>
but you can also place the keydef right in the frontmatter.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Tinmen
Posts: 21
Joined: Wed Jun 28, 2023 11:49 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Tinmen »

Thanks, Radu.

I think I'm getting closer, but I am now running into an imagepreoloader error.

cover page ditamap

Code: Select all

<data name="coverImage" keyref="coverImage"/>
keydefs.ditamap

Code: Select all

<keydef keys="coverImage" href="coverart1.png" format="png"/>
front-matter.xsl

Code: Select all

<fo:block text-align="center" width="100%">
           <xsl:value-of select="//bookmeta/data/@name"/> <!-- prints the value in the PDF for testing and error checking -->
           <fo:block><xsl:value-of select="//bookmeta/data[@name='coverImage']/@href"/></fo:block><!-- prints the value in the PDF for testing and error checking -->
           <fo:external-graphic select="resolve-uri((//bookmeta/data[@name='coverImage']/@href)[1])"/>
        </fo:block> 
PDF Output
coverImage
maps/coverart1.png
... no image appears - Note: I have an image named coverart1.png in the maps directory.

Oxygen Error
Image not available. URI: . Reason: org.apache.xmlgraphics.image.loader.ImageException: The file format is not supported. No ImagePreloader found for (See position 1:16998)
Radu
Posts: 9059
Joined: Fri Jul 09, 2004 5:18 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Radu »

Hi,
Can you also add an xsl:message or use xsl:value-of to output the value of the "resolve-uri((//bookmeta/data[@name='coverImage']/@href)[1])" xpath?
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Tinmen
Posts: 21
Joined: Wed Jun 28, 2023 11:49 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Tinmen »

Hi Radu:

Generates the following:
file:/Applications/Oxygen%20XML%20Editor/Custom/CustomizationoXygen/Customization-PDF/fo/xsl/maps/coverart1.png
On another note, If I hardcode the following in my front-matter.xsl file and move the coverart1 image to the specified /artwork directory; I can get the image to appear in the PDF.

Code: Select all

<fo:external-graphic src="url({concat($artworkPrefix,'Customization/OpenTopic/common/artwork/coverart1.png')})"/></fo:block>
However, if I try to change anything in this path, for example:

Code: Select all

<fo:external-graphic src="url({concat($artworkPrefix,'Customization/OpenTopic/common/coverart/coverart1.png')})"/></fo:block>
and I move the coverart1.png file to the /coverart directory; the image will not render in the PDF.

I can change the image's file name in the original path and add that image to the /artwork directory, and the image will render in the PDF, but anything outside of the original path doesn't appear to work.

This is not a solution I need, in any case, as the writers want to be able to specify their own file names and not have to place image files in the XSL directories.
Regards

Tinmen
Radu
Posts: 9059
Joined: Fri Jul 09, 2004 5:18 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Radu »

Hi Tinmen,

How about if you try something like:

Code: Select all

resolve-uri((//bookmeta/data[@name='coverImage']/@href)[1], base-uri(.))
?
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Tinmen
Posts: 21
Joined: Wed Jun 28, 2023 11:49 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Tinmen »

Thanks, Radu.

I tried the code, but no image appears.

The value of output is:
file:/Users/tinmen/Desktop/testing/temp/pdf/maps/coverart1.png
When I review the contents of the temp directory during PDF render time, almost everything needed is there, including the maps directory. The maps directory contains keydef.ditamap file but not the actual coverart1.png file. That image file is not picked up or copied to the temp pdf maps directory.

Regards

Tinmen
Radu
Posts: 9059
Joined: Fri Jul 09, 2004 5:18 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Radu »

Hi Tinmen,
From what I remember the PDF transformation indeed might not copy the binary files and images to the transformation temporary files folder. So they would need to be referenced directly from the input folder.
In the transformation temporary files folder there should be a ".job.xml" file which maps all input files to their reference equivalents.
If you look inside "DITA-OT/plugins/org.dita.pdf2/xsl/fo/topic.xsl" at the xsl:template which matches an image:

Code: Select all

<xsl:template match="*[contains(@class,' topic/image ')]" name="image">
it attempts to look inside the .job.xml file to find the original location of the image, then use this location, or uses the original relative href to the image and appends it to the "input.dir.url" to create an absolute path pointing to the image in the input folder:

Code: Select all

                              <xsl:when test="exists(key('jobFile', @href, $job))">
                                <xsl:value-of select="key('jobFile', @href, $job)/@src"/>
                              </xsl:when>
                              <xsl:otherwise>
                                <xsl:value-of select="concat($input.dir.url, @href)"/>
                              </xsl:otherwise>
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Tinmen
Posts: 21
Joined: Wed Jun 28, 2023 11:49 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Tinmen »

Thanks again, Radu, for all your help.

Based on your information, I coded the following, which now works and renders an image on the cover page:

Code: Select all

fo:block>
  <fo:external-graphic width="75mm" src="url({concat($input.dir.url, 'coverart/coverart1.png')})"/>
</fo:block>
This will work for now for my needs.
Regards
Tinmen
Sano
Posts: 11
Joined: Mon Jan 19, 2015 11:11 am

Re: Trying to print a custom image on Cover Page in PDF

Post by Sano »

After some back and forth with the ideas in this thread, the following code works in my customized pdf2 plugin to distribute a dynamic cover image via a data element with a name="CoverImage" contained in the DITAMAP.

Code: Select all

 <fo:external-graphic>
       <xsl:attribute name="src" select="resolve-uri((//data[@name='CoverImage']//image/@href[1]),$input.dir.url)"/>
 </fo:external-graphic>
This locates the original image in a folder next to your input DITAMAP, not in temp or plugin folders.
The data element contains an image with conkeyref to another library topic/image.

Code: Select all

<data id="CoverImage" name="CoverImage">
     <image conkeyref="key/image-id" id="image_scr_ddg_tyb"/>
</data>
My Environment
  • DITA-OT from O2 25.1
  • This solution works with standard maps without frontmatter section
  • I use DITA project files to generate output.
Problems I had to solve:
  • It is not possible to insert xpath directly into "src" attribute of external-graphic because it will not be resolved.
  • The select attribute is not available for external-graphic element.
  • I had no success with baseuri() because it targets ../stage1.xml if you use it to build an absolute path to the image.
  • To scale the external-graphic use the attribute content-width instead of width.
Radu
Posts: 9059
Joined: Fri Jul 09, 2004 5:18 pm

Re: Trying to print a custom image on Cover Page in PDF

Post by Radu »

HI Sano,
About these two remarks:
It is not possible to insert xpath directly into "src" attribute of external-graphic because it will not be resolved.
The select attribute is not available for external-graphic element.
The produced XSLT-FO file needs to be fully resolved, this is how the XSL-FO standard works, it cannot contain inside it other xpath expressions, the PDF processor which produces the PDF file from the XSL-FO file is not an XSLT engine and does not resolve xpath expressions.
These are all the attributes which can be set on the produced fo:external-graphic element:
http://www.datypic.com/sc/fo11/e-fo_ext ... aphic.html

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Post Reply