2012年12月3日月曜日

Customizing the way images are stored

Every time you call one of the drawImage methods provided by the Graphics2D interface, a default representation of your image is created in a location and put in a default file. For instance, a base64 encoding is created and embedded in the SVG file by default. Alternatively, you can choose to have your images written to separate files in a predefined directory, in one of the two raster formats required by the SVG specification: JPEG or PNG.

You can change the default behavior by explicitly providing the image handler to be used by the SVG generator. Once again, you use the SVGGeneratorContext for this. In the example below, all images are converted to PNG format and written to directory res/images.

DOMImplementation impl = GenericDOMImplementation.getDOMImplementation();
String svgNS = "http://www.w3.org/2000/svg";
Document myFactory = impl.createDocument(svgNS, "svg", null);

SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(myFactory);
GenericImageHandler ihandler = new ImageHandlerPNGEncoder("res/images", null);
ctx.setImageHandler(ihandler);
SVGGraphics2D g2d = new SVGGraphics2D(ctx, false);

Using the default image handlers results in a new copy of the image data being written to the SVG file or an external file, for every single drawImage call. If you use the same images over and over again, then this may result in an SVG file containing a lot of redundant data. At the price of a slight performance penalty during initial generation of the SVG DOM tree, you can choose to have your image data reused. For this you use a specialized image handler, as shown below.

DOMImplementation impl = GenericDOMImplementation.getDOMImplementation();
String svgNS = "http://www.w3.org/2000/svg";
Document myFactory = impl.createDocument(svgNS, "svg", null);

SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(myFactory);

// Reuse our embedded base64-encoded image data.
GenericImageHandler ihandler = new CachedImageHandlerBase64Encoder();
ctx.setGenericImageHandler(ihandler);

SVGGraphics2D g2d = new SVGGraphics2D(ctx, false);

With the caching image handlers, it is even possible to reuse the same copy of your image data across several different SVG documents. Just keep a reference to the image handler, and pass it to the SVGGraphics2D instance used for generating the SVG DOM tree. The following simplified example shows how different SVG trees might be created by separate SVG generators, efficiently storing any common images just once.


class MySVGGenerator {

// The image handler will write all images files to "res/images".
private static ImageHandler ihandler =
new CachedImageHandlerPNGEncoder("res/images", null);

public void generateSVG(JPanel myCanvas, OutputStream outStream) {
DOMImplementation domImpl =
GenericDOMImplementation.getDOMImplementation();
Document myFactory = domImpl.createDocument(svgNS, "svg", null);
SVGGeneratorContext ctx =
SVGGeneratorContext.createDefault(myFactory);
ctx.setGenericImageHandler(ihandler);

SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false);

// Create the SVG DOM tree.
myCanvas.paintComponent(svgGenerator);

Writer out = new OutputStreamWriter(outStream, "UTF-8");
svgGenerator.stream(out, true);
}
}

0 件のコメント:

コメントを投稿