<?xml version="1.0"?>
<!DOCTYPE document SYSTEM "./dtd/document-v10.dtd">

<!-- ========================================================================= -->
<!-- Copyright (C) The Apache Software Foundation. All rights reserved.        -->
<!--                                                                           -->
<!-- This software is published under the terms of the Apache Software License -->
<!-- version 1.1, a copy of which has been included with this distribution in  -->
<!-- the LICENSE file.                                                         -->
<!-- ========================================================================= -->

<!-- ========================================================================= -->
<!-- author tkormann@apache.org                                                -->
<!-- version $Id$ -->      
<!-- ========================================================================= -->

<document>
    <header>
        <title>Image Transcoder Tutorial</title>
        <subtitle>A brief introduction to the image transcoder API</subtitle>
        <authors>
            <person name="Thierry Kormann" email="tkormann@apache.org"/>
        </authors>
    </header>

    <body>

<!-- ##################################################################### -->
<s1 title="Introduction">
  <p>
    The goal of the transcoder API (package
    <code>org.apache.batik.transcoder</code>) is to provide a generic
    API for transcoding an input to an output. First, this document
    explains the basic transcoder API that <code>Transcoder</code>,
    <code>TranscoderInput</code> and <code>TranscoderOutput</code>
    define -- and thus all transcoders have in common. Next, it
    describes how to use the image transcoder API (package
    <code>org.apache.batik.transcoder.image</code>) which lets you
    rasterize an SVG document fragment to a raster image such as JPEG
    or PNG.
  </p>
</s1>

<s1 title="The Transcoder API">
<p>
The <code>org.apache.batik.transcoder</code> package defines 5 major classes:
</p>
<dl>
<dt><code>Transcoder</code></dt>
<dd>
Defines the interface that all transcoders implement. You can
transcode a specific input using a specific output by invoking the
<code>transcode</code> method. Although there is no assumption on the
input and output format, a specific transcoder may or may not support
a particular type of input or output. For example, the image
transcoders accept an SVG <code>org.w3c.dom.Document</code>, a
<code>Reader</code>, an <code>InputStream</code>, or a
<code>URI</code> as an input but only supports a byte stream for the 
output.
<br /><br />
</dd>

<dt><code>TranscoderInput</code></dt>
<dd>
Defines the input of a transcoder. There are various ways to create an
input and the most commons are already part of the API. The default
implementation lets you create an input using a
<code>org.w3c.dom.Document</code>, a <code>Reader</code>, an
<code>InputStream</code>, a <code>org.xml.sax.XMLReader</code>, or a
<code>URI</code>.
<br /><br />
</dd>

<dt><code>TranscoderOutput</code></dt>
<dd>
Defines the output of a transcoder. There are various ways to create an
output and the most commons are already part of the API. The default
implementation lets you create an output using a
<code>org.w3c.dom.Document</code>, a <code>Writer</code>, an
<code>OutputStream</code>, a <code>org.xml.sax.XMLFilter</code>, or a
<code>URI</code>.
<br /><br />
</dd>

<dt><code>TranscodingHints</code></dt>
<dd>
The <code>TranscodingHints</code> class contains different hints which can
be used to control the various options or parameters of a
transcoder. Each transcoder provides its own set of hints. A hint is
specified by (key, value) pair. For example, the
<code>JPEGTranscoder</code> provides a hint to control the encoding quality.
<br /><br />
</dd>

<dt><code>ErrorHandler</code></dt>
<dd>
This class provides a way to get the errors and/or warnings that might
occur while transcoding. A default implementation is provided but
you can, for example, implement your own handler that display a dialog
instead of stack trace.
</dd>
</dl>
</s1>

<!-- ##################################################################### -->
<s1 title="How to Use the Image Transcoder API">
<p>
The <code>org.apache.batik.transcoder.image</code> package provides an
easy way to transcode an SVG document to a raster image such as JPEG or
PNG. Additional raster image formats can be added by subclassing the
<code>ImageTranscoder</code> and implementing the
<code>writeImage</code> method. Although, in next sections, the
examples will use the JPEG transcoder, the PNG transcoder works the
same way.
</p>

<s2 title="Creating an Image">
<p>
The following example, using the <code>JPEGTranscoder</code> shows how to
trasnform a SVG document to a JPEG image.
</p>
<source>
SaveAsJpeg.java
===============

import java.io.*;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;

public class SaveAsJPEG {

    public static void main(String [] args) throws Exception {

        // create a JPEG transcoder
        <strong>JPEGTranscoder t = new JPEGTranscoder();</strong>
        // set the transcoding hints
        <strong>t.addTranscodingHint(JPEGTranscoder.KEY_XML_PARSER_CLASSNAME,
                             "org.apache.crimson.parser.XMLReaderImpl");</strong>
        <strong>t.addTranscodingHint(JPEGTranscoder.KEY_QUALITY,
                             new Float(.8));</strong>
        // create the transcoder input
        String svgURI = new File(args[0]).toURL().toString();
        <strong>TranscoderInput input = new TranscoderInput(svgURI);</strong>
        // create the transcoder output
        OutputStream ostream = new FileOutputStream("out.jpg");
        <strong>TranscoderOutput output = new TranscoderOutput(ostream);</strong>
        // save the image
        <strong>t.transcode(input, output);</strong>
        // flush and close the stream then exit
        ostream.flush();
        ostream.close();
        System.exit(0);
    }
}
</source>
<p>
The code creates a <code>JPEGTranscoder</code> and sets the
transcoding hints. The first hint indicates the XML parser to use. The
second hint sets the encoding quality. Then, an input and an output
are created. The input is created using the first command line
argument which should represent a URI. The output is a byte stream
representing a file called "out.jpg". Finally, the
<code>transcode</code> method is invoked and the byte stream is
closed.
</p>
<p>
Although not shown above, the program might have specified additional
hints to indicate a user style sheet, the preferred language of the
document or the background color.
</p>
<p>
<strong>Try this:</strong>
</p>
<ol>
<li>Compile and run the program: SaveAsJPEG.java. You will need a SVG document.<br />
<code>% java SaveAsJPEG &lt;filename>.svg</code></li>
<li>Take a look at: out.jpg</li>
</ol>
</s2>


<s2 title="Defining the Size of the Image">
<p>
By adding the following line of code to the previous example, you will
specify the raster image size (in pixels). The new transcoding hint
<code>KEY_WIDTH</code> lets you specify the raster image width. As the
raster image height is not provided (using the
<code>KEY_HEIGHT</code>), the transcoder will compute the raster image
dimension by keeping the aspect ratio of the SVG document.
</p>
<source>
t.addTranscodingHint(JPEGTranscoder.KEY_WIDTH, new Integer(100));
</source>
<p>
The transcoder will have the same behavior if you specify the
<code>KEY_HEIGHT</code> without initializing the
<code>KEY_WIDTH</code>. In all cases (though both keys are provided),
the transcoder will preserve the apsect ratio of the SVG document.
</p>
</s2>

<s2 title="Selecting an Area of Interest">
<p>
The image transcoder lets you specify an area of interest (ie. a part
of the SVG document). The key <code>KEY_AOI</code> enables to select
the region of the SVG document to render. The value of this key must
be a <code>java.awt.Rectangle</code> specified in pixels and described
in the SVG document's space. The following example shows how you can
split a SVG document into 4 tiles.
</p>
<source>
SaveAsJPEGTiles.java
====================

import java.io.*;
import java.awt.*;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;

public class SaveAsJPEGTiles {

    JPEGTranscoder trans = new JPEGTranscoder();

    public SaveAsJPEGTiles() {
        trans.addTranscodingHint(JPEGTranscoder.KEY_XML_PARSER_CLASSNAME,
                                 "org.apache.crimson.parser.XMLReaderImpl");
        trans.addTranscodingHint(JPEGTranscoder.KEY_QUALITY,
                                 new Float(.8));
    }

    public void tile(String inputFilename,
                     String outputFilename,
                     Rectangle aoi) throws Exception {
        <strong>trans.addTranscodingHint(JPEGTranscoder.KEY_WIDTH,
                                 new Float(aoi.width));</strong>
        <strong>trans.addTranscodingHint(JPEGTranscoder.KEY_HEIGHT,
                                 new Float(aoi.height));</strong>
        <strong>trans.addTranscodingHint(JPEGTranscoder.KEY_AOI, aoi);</strong>
        String svgURI = new File(inputFilename).toURL().toString();
        TranscoderInput input = new TranscoderInput(svgURI);
        OutputStream ostream = new FileOutputStream(outputFilename);
        TranscoderOutput output = new TranscoderOutput(ostream);
        trans.transcode(input, output);
        ostream.flush();
        ostream.close();
    }

    public static void main(String [] args) throws Exception {
        SaveAsJPEGTiles p = new SaveAsJPEGTiles();
        <strong>String in = "samples/anne.svg";
        int documentWidth = 450;
        int documentHeight = 500;</strong>
        int dw2 = documentWidth / 2;
        int dh2 = documentHeight / 2;
        p.tile(in, "tileTopLeft.jpg", new Rectangle(0, 0, dw2, dh2));
        p.tile(in, "tileTopRight.jpg", new Rectangle(dw2, 0, dw2, dh2));
        p.tile(in, "tileBottomLeft.jpg", new Rectangle(0, dh2, dw2, dh2));
        p.tile(in, "tileBottomRight.jpg", new Rectangle(dw2, dh2, dw2, dh2));
        System.exit(0);
    }
}
</source>
<p>
This code splits the same document "anne.svg" into four tiles of the
same size. Considering the document and its original size, we can
determine four regions. Then we rasterize each region using the
<code>KEY_AOI</code> key. Note that we also specify the image width
and height to be the same as the area of interest width and height (so
we keep a 1:1 zoom factor). You can of course combine the
<code>KEY_WIDTH</code>, <code>KEY_HEIGHT</code> keys with the
<code>KEY_AOI</code>. In that case, first the area of interest will
determine which part of the SVG document has to be rendered - then
that part could be zoom in or out depending on the specified raster
image size.
</p>
<p>
<strong>Try this:</strong>
</p>
<ol>
<li>Compile and run the program: SaveAsJPEGTiles.java. You will need the "anne.svg" document.<br />
<code>% java SaveAsJPEGTiles</code></li>
<li>Take a look at: tileTopRight.jpg, tileTopRight.jpg, tileBottomRight.jpg
 and tileBottomLeft.jpg</li>
</ol>
</s2>

<s2 title="Generating an Image from a SVG DOM Tree">
<p>
The following code creates and saves a SVG DOM tree.
</p>
<source>
DOMRasterizer.java
==================

import java.io.*;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.DOMImplementation;

public class DOMRasterizer {

    public Document createDocument() {
        <strong>DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
        String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;
        Document document =
            impl.createDocument(svgNS, "svg", null);
        Element root = document.getDocumentElement();</strong>
        root.setAttributeNS(null, "width", "450");
        root.setAttributeNS(null, "height", "500");

        Element e;
        e = document.createElementNS(svgNS, "rect");
        e.setAttributeNS(null, "x", "10");
        e.setAttributeNS(null, "y", "10");
        e.setAttributeNS(null, "width", "200");
        e.setAttributeNS(null, "height", "300");
        e.setAttributeNS(null, "style", "fill:red;stroke:black;stroke-width:4");
        root.appendChild(e);

        e = document.createElementNS(svgNS, "circle");
        e.setAttributeNS(null, "cx", "225");
        e.setAttributeNS(null, "cy", "250");
        e.setAttributeNS(null, "r", "100");
        e.setAttributeNS(null, "style", "fill:green;fill-opacity:.5");
        root.appendChild(e);

        return document;
    }

    public void save(Document document) throws Exception {
        JPEGTranscoder t = new JPEGTranscoder();
        t.addTranscodingHint(JPEGTranscoder.KEY_QUALITY,
                             new Float(.8));
        <strong>TranscoderInput input = new TranscoderInput(document);</strong>
        OutputStream ostream = new FileOutputStream("out.jpg");
        TranscoderOutput output = new TranscoderOutput(ostream);
        t.transcode(input, output);
        ostream.flush();
        ostream.close();
    }

    public static void main(String [] args) throws Exception {
        DOMRasterizer rasterizer = new DOMRasterizer();
        Document document = rasterizer.createDocument();
        rasterizer.save(document);
        System.exit(0);
    }
}
</source>
<p>
This code is divided into two distinct parts. 
</p>
<dl>
<dt>Creating a SVG DOM tree</dt>
<dd>
<br />See the <code>createDocument</code> method<br /> Three steps are
required at this time. The first one consists on getting the Batik SVG
DOM implementation (via the SVGDOMImplementation class). Then, you can
create a <code>org.w3c.dom.Document</code> (which is a SVG Document by
the way) by invoking the <code>createDocument</code> method with the
svg namespace URI and the "svg" document element. At last, you can get
the document element and start to build your DOM tree.  <br /><br />
</dd>
<dt>Rasterizing your DOM</dt>
<dd>
<br />See the <code>save</code> method<br /> Similar to the previous
examples, you can transcode a SVG document to a raster image by
creating a <code>TransocderInput</code> with this time, the SVG Document.
<br /><br />
</dd>
</dl>
<p>
<strong>Try this:</strong>
</p>
<ol>
<li>Compile and run the program: DOMRasterizer.java.<br />
<code>% java DOMRasterizer</code></li>
<li>Take a look at: out.jpg</li>
</ol>
</s2>

</s1>


    </body>
</document>
  