Images

Image basics

Images are added to the document using either the fo:external-graphic or fo:instream-foreign-object elements. The fo:external-graphic element is used to include a file in JPEG, GIF, TIFF, BMP, SVG or PNG formats.
The fo:instream-foreign-object element is used to include an image defined in Scalable Vector Graphics (SVG) format where the image SVG is contained within the FO.

The properties used to format the fo:external-graphic and fo:instream-foreign-object elements are the same. The size of the image is distinct from the size of the area in which the image is placed. The height and width attributes on the external-graphic or instream-foreign-object element specify the size of the area into which the graphic will be placed.
If these properties are not specified they default to an area large enough to contain the image.

The content-width and content-height attributes control the size of the image. These can be values such as "3cm" or percentages such as "120%". If content-width and content-height not specified the image defaults to the size in pixels specified in the image file itself. This means that if you do not specify any of the above attributes the image will be as large as specified in the image file, and will be placed in an area the same size.

The dots per inch (dpi) value of the image makes a difference to the image size. Two images can have the same dimensions in pixels but appear different sizes in the PDF file. This is because Ibex uses the dpi value to work out the size of the image. An image which is 300 pixels wide and stored at 300 dpi will be 1 inch wide. The same image stored at 100 dpi will be 3 inches wide.

An image is an inline element, so for formatting purposes it can be placed in a sentence surrounded by text and is treated as a single word.

The fo:external-graphic element is used to include an image which is in a file external to the FO file. The name of the file to be included is specified using the src attribute. The src attribute is called a uri-specification and must follow the following rules: A sequence of characters that is "url(", followed by optional white space, followed by an optional single quote (') or double quote (") character, followed by a URI reference as defined in [RFC2396], followed by an optional single quote (') or double quote (") character, followed by optional white space, followed by ")". The two quote characters must be the same and must both be present or absent. If the URI reference contains a single quote, the two quote characters must be present and be double quotes.

This means the following are all valid values for the src attribute:

As the src attribute is a URL, an image which exists on a web server can be downloaded automatically by Ibex as the PDF file is created. This is common in real estate and catalog applications and means you do not need to make a copy of an existing image just to get it into the PDF file. The FO shown in Figure 15-1 will fetch the file download2.gif from http://www.xmlpdf.com.

<fo:block space-before="6pt">
   <fo:external-graphic border="1pt solid black" src="url(http://www.xmlpdf.com/images/download2.gif)" 
     content-width="200%" content-height="200%"/>
</fo:block>

Figure 15-1: FO to insert an image from a web server

The fo:external-graphic element can be used to include image files in PNG, JPEG, TIFF, BMP, SGV and GIF formats.

The fo:instream-foreign-object is used for loading images from SVG content that is contained inline in the FO.
See SVG Images on page SVG.

Making an image fit a specified space

To make an image fit a specified size use the height and width attributes to specify the size of the fo:external-graphic element, and then use the content-width and content-height to fit the image to the size specified on the fo:external-graphic element. For example to fit an image into an area 2cm x 2cm, set the width and height attributes to "2cm" and set the content-width and content-height attributes to "scale-to-fit".

<fo:external-graphic src="url(image.jpg)"
	height="2in" width="2in" 
	content-height="scale-to-fit"  
	content-width="scale-to-fit"/>

Figure 15-2: Scaling an image

If you only want the image reduced in size to fit the specified area and do not want it increased in size if it is smaller, specify content-width="scale-down-to-fit". This also applies to content-height. If you only want the image enlarged to fit the specified area and do not want it reduced in size if it is larger, specify content-width="scale-up-to-fit". This also applies to content-height.

Clipping

If the image is larger than the area in which it is contained then the image may be clipped.

If we specify the height of the fo:external-graphic element as 2.5cm and specify overflow="hidden", the image will be clipped to this height.

If we specify the height of the fo:external-graphic element as 2.5cm and do not specify overflow="hidden", the image will not be clipped to this height, and will overwrite other content as shown to the right. Because the image is positioned on the same baseline as text, the overflow will be at the top of the area containing the image.

Image size and alignment

If an image is smaller than the containing area we can control where it appears in that area using the display-align and text-align attributes. The display-align attribute controls the vertical alignment, text-align controls the horizontal alignment. By default the image appears in the top left corner of the inline area created by the fo:external-graphic or fo:instream-foreign-object element, as shown in Figure 15-3

Figure 15-3: Default image alignment

If we specify text-align="center" the image will move to the horizontal center of the inline area, as shown in Figure 15-4.

Figure 15-4: Centered image alignment

The image is an inline element and can be treated like a normal word, so that attributes such as "text-align" apply can be used. If we specify text-align="center" and display-align="center" the image will move to the horizontal and vertical center of the inline area, as shown in Figure 15-5.

Figure 15-6: Image horizontal and vertical alignment

Leading

Looking at the image in Figure 15-7 you can see a gap between the top of the image and the border. This is the leading, which appears because the image is treated as a text element and sits on the baseline. The amount of leading is derived from the font size, so you can reduce it to zero by setting the font size to zero, by specifying font-size="0pt" on the containing block element. This has been done in Figure 15-8.

Figure 15-7: Image showing leading

Figure 15-8: Image with no leading

Image resolution

The resolution of an image in dots per inch (dpi) can be set using the dpi attribute on the fo:external-graphic element.

Setting this attribute overrides the dpi value read from the image file.

Setting the dpi to a lower value than the one specified in the image will result in smaller image of lower quality than the original. This is often done to reduce the size of the image in the PDF file and can result in massive decreases in PDF file size. If you have an image which is stored at 2400 dpi, and your end user will display it on a 96 dpi screen or print it on 600 dpi printer, reducing the image dpi to 600 will not effect the appearance of the image.

Setting the dpi to a value higher than the value read from the image file has no effect. If for example if we wanted to store an image in the PDF file at 1200 dpi, we would use the FO shown in Figure 15-9.

<fo:block space-before="6pt">
  <fo:external-graphic border="1pt solid black" 
      src="url(http://www.xmlpdf.com/images/download2.gif)" 
      content-width="200%" content-height="200%"
      dpi="1200"/>
</fo:block>

Figure 15-9: FO to set image dpi

The dpi attribute is an Ibex extension. It is not part of the XSL-FO standard.

Image anti-aliasing

Images are anti-aliased by default. This can be disabled using the ibex:anti-alias attribute as shown in figure Figure 15-10.

<fo:block space-before="6pt">
  <fo:external-graphic 
      src="url(http://www.xmlpdf.com/images/download2.gif)" 
      ibex:anti-alias="false"
      dpi="1200"/>
</fo:block>

Figure 15-10: FO to disable anti-aliasing

Figure 15-11: Images with and without anti-aliasing

Figure 15-11 shows two images, the left right one has anti-aliasing disabled so the edges of the image appear more clearly. The ibex:anti-alias attribute is an Ibex extension. It is not part of the XSL-FO standard.

Loading an image from memory

Ibex has the facility to load an image which is stored in memory. This permits an application to dynamically generate an image or to load an image from a database for inclusion in the PDF file. The image must be passed to Ibex in a byte array or a Stream (from the System.IO namespace). The image must be given a unique identifier by which it can be retrieved during the PDF creation process. This is done using the addNamedImage() method on the FODocument object. This method takes two parameters; (1) a string which identifies the image and (2) the stream or array which contains the image itself. For example if we had an image in a byte array called "image" and we wanted to give it the identifier "1029" we would use the code shown in Figure 15-12 to do this.

byte[] image = ... dynamically create
FODocument document = new FODocument();
document.addNamedImage( "1029", image );

Figure 15-12: C# code to load an image from memory

This must be done before calling generate() to create the PDF file. Within the FO file the image is retrieved from memory using the syntax shown in Figure 15-13

<fo:external-graphic src="url(data:application/ibex-image,1029)"/>

Figure 15-13: FO to load an image from memory

The value of the src attribute must be the string "url(data:application/ibex-image," followed by the unique identifier which was passed to addNamedImage(). This syntax for the url attribute conforms to RFC 2397 - The "data" URL scheme (which can be found at http://www.faqs.org/rfcs/rfc2397.html).

Transparent GIF images

GIF images which have transparent areas are supported. The FO in Figure 15-14 places the same transparent GIF image on two different backgrounds.

<fo:block background-color="blue">
	<fo:external-graphic src="url(ibm-logo.gif)" content-height="2cm"/>
</fo:block>
<fo:block background-color="black">
	<fo:external-graphic src="url(ibm-logo.gif)" content-height="2cm"/>
</fo:block>

Figure 15-14: FO for transparent image

Transparent PNG images

PNG images which have transparent areas are supported. The FO in Figure 15-15 places a transparent PNG image on a white backgrounds.

<fo:block background-color="white">
		<fo:external-graphic src="url(RedbrushAlpha-0.25.png)" content-height="2cm"/>
</fo:block>

Figure 15-15: FO for transparent image

Transparent images using masking

Ibex can use image masking to make some parts of an image appear transparent. This is an extension to the standard. Image masking works by defining colors from the image which should not be displayed. The PDF viewer will compare each pixel in the image with the mask and not display pixels which match the mask, effectively making these pixels transparent and so leaving visible the content behind the image. The image mask is defined using the <fo:ibex:mask> element, which must be contained within an fo:external-graphic element, as shown in Figure 15-16.

<fo:external-graphic src="url(ixsl.jpg)"  z-index='10'>
	<fo:ibex:mask 
	       red-min="255" red-max="255"   
	       green-min="255" green-max="255"  
	       blue-min="255" blue-max="255"/>
</fo:external-graphic>

Figure 15-16: FO to mask an image

To use the ibex:mask element you must reference the ibex namespace in your FO as shown in Figure 15-17.

<fo:root 
  xmlns:fo="http://www.w3.org/1999/XSL/Format" 
  xmlns:ibex="http://www.xmlpdf.com/2003/ibex/Format">

Figure 15-17: Referencing the ibex namespace

The mask defines the minimum and maximum values for each of the red, green and blue components of an image. A mask using these values is applicable only to images which are in RGB format with 24 bits per pixel. For CMYK images, attributes called c-min, c-max, m-min, m-max, y-min, y-max, k-min and k-max define the minimum and maximum values for each of the cyan, magenta, yellow and black components of the image. The image mask shown above causes any pixel which has red=255, green=255 and blue=255 to not be rendered.

As a pixel with red, green and blue all equal to 255 is white, this means any white pixels will not be rendered.

Transparent Images using SVG

Transparent images can also be implemented by placing a SVG image over the top of other content. This approach uses the vector SVG renderer introduced in Ibex 2.1.2 and is only available when using .NET 1.1 or higher. This is the best approach for transparent images because (a) there is no background on the SVG image so the best clarity is achieved, and (b) SVG uses a vector renderer which creates a smaller PDF file than you would get using a bitmap image. Figure 15-18 shows the FO to put the word "ibex" over some text.

<fo:block-container>
  <fo:block-container space-before="6pt" absolute-position="absolute" top="-1.6cm" left="5cm">
    <fo:block>
       <fo:instream-foreign-object z-index="30">
          <fo:svg width="315" height="100" 
              xmlns="http://www.w3.org/2000/svg">
               <fo:text  x="30" y="60" fill="blue" stroke="blue" 
                  font-size="61pt" font-style="italic"
                  style="font-family:arial;stroke-width:0.5">
                  Ibex
               </fo:text>
          </fo:svg>
       </fo:instream-foreign-object>
    </fo:block>
  </fo:block-container>
</fo:block-container>

Figure 15-18: FO using SVG to place content over text

Network credentials used in accessing images

Ibex can retrieve images from HTTP servers as shown in Figure 15-19 below. By default Ibex will do this using the credentials of the process which is creating the PDF file. If Ibex is running in an ASP.NET server then the default configuration is that ASP runs as the ASPNET user. This user does not have permissions to access other servers and so will not be able to retrieve images from other servers.

<fo:block space-before="6pt">
   <fo:external-graphic border="1pt solid black" src="url(http://www.xmlpdf.com/images/download2.gif)" content-width="200%" content-height="200%"/>
</fo:block>

Figure 15-19: FO to insert an image from an HTTP server

The FODocument object supports the setNetworkCredentials() method. This method takes 4 parameters, as shown in Figure 15-20.

public void setNetworkCredentials( 
    string prefix, 
    string username, 
    string password, 
    string domain ) 

Figure 15-20: The setNetworkCredentials method

The parameters are:

Name Description
prefix The start of a URL, such as "http://www.xmlpdf.com". Any image URL which starts with this prefix will use these credentials.
username the username passed to the remote server
password the password passed to the remote server
domain the domain name passed to the remote server

Each call to setNetworkCredentials() is passed a prefix which is compared with image URLs to see which set of credentials to use.

For example if your application accesses two HTTP servers using different credentials your code might look like the code in Figure 15-21. Obviously you would get the username and password information from somewhere in your application rather than hard coding them.

FODocument doc = new FODocument()
doc.setNetworkCredentials( "http://www.xmlpdf.com","user1","password1","domain1" );
doc.setNetworkCredentials( "http://www.ibex4.com","user2","password2","domain2" );

Figure 15-21: Setting credentials for different servers

Internally Ibex uses the System.Net.WebRequest and System.Net.NetworkCredential objects to pass credentials to the remote server. If credentials have been passed to Ibex using the setNetworkCredentials() method a new NetworkCredential object is created when creating the WebRequest object. SO the actual forwarding of the credentials to the remote server is all done by .Net. Calls to setNetworkCredentials() should be made before the generate() method is called.

Multi-page TIFF image processing

Ibex has an extension attribute "ibex:page" which is used to specify which page of a multi-page TIFF image should be included in the PDF file. FO to place the third page of a multi-page TIFF image is shown in Figure 15-22.

<fo:block>
		<fo:external-graphic src="url('7pages.tif')" ibex:page="3"/>
</fo:block>

Figure 15-22: Specifying the page of a multi-page TIFF image