Export to a vector format

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
Zappo
Posts: 9
Joined: Thu Jan 31, 2008 8:53 pm

Export to a vector format

Post by Zappo » Wed Feb 13, 2008 11:15 am

Hi all! :)

I'd like to be able to export a chart to some kind of vector image format, such as WMF or EPS.

I've searched the forums and I've found several ways to create vector files, but all of them actually still result in a bitmap; what I'm trying to do is a "real" vector export, containing the actual lines and whatnot, that can be arbitrarily zoomed.

Has anyone done any work to this purpose? Are there any libraries I could use? Any help would be useful. :)

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Post by paradoxoff » Wed Feb 13, 2008 12:30 pm

Can you be a little more specific about what you have tried?
I am using freehep (http://java.freehep.org/vectorgraphics/index.html, download ftp://ftp.slac.stanford.edu/software/fr ... cs/v2.1.1/, I am not sure about the minimum JAR files that are required so I got them all) for the generation of EMF files (the format behind MSOffice vectorgraphics) and an EPS generator from the Apache XML Graphics Commons package (http://xmlgraphics.apache.org/commons/). Both work fine, but the EMF files are much better suited for import into word or powerpoint. EPS files looked bad after import but are fine in ghostscript, so the fault is probably on the MSOffice side.
I will post some sample code this evening.
Regards, paradoxoff

Zappo
Posts: 9
Joined: Thu Jan 31, 2008 8:53 pm

Post by Zappo » Wed Feb 13, 2008 12:34 pm

I haven't tried anything specific yet, I'm still looking around for the best solution. Unfortunately, while I've seen several ways to create images in a vector format, none of them create actual vector images. They're all bitmaps embedded in a vector format, which kinda defeats the purpose. I'm really interested in seeing your sample code. :)

mhilpert
Posts: 497
Joined: Wed Apr 02, 2003 1:57 pm
Location: Germany

Post by mhilpert » Wed Feb 13, 2008 1:31 pm

Code: Select all

    /**
     * Save chart as SVG file.
     * Required libs: Apache Batik (batik-svggen.jar, batik-dom.jar, dom.jar).
     * 
     * @param chart JFreeChart to save.
     * @param fileName Name of file to save chart in.
     * @param width Width of chart graphic.
     * @param height Height of chart graphic.
     * @return Final file name used.
     * @throws IOException if failed.
     */
    static public final String saveChartToSVG(final JFreeChart chart, String fileName, final int width, final int height) throws IOException {
        String result = null;
        
        if (chart != null) {
            if (fileName == null) {
                final String chartTitle = chart.getTitle().getText();
                if (chartTitle != null) {
                    fileName = chartTitle;
                } else {
                    fileName = "chart";
                }
            }
            result = fileName + ".svg";
            
            final DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
            final Document document = domImpl.createDocument(null, "svg", null);
            final SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
            
//            svgGenerator.getGeneratorContext().setEmbeddedFontsOn(true); //embed fonts
            
            //set anti-aliasing bug fix for SVG generator:
            //setting rendering hints of svgGenerator doesn't help as it seems to use the rendering hints from the chart
            final boolean antiAlias = isAntiAliasOn(chart);
            final RenderingHints rh = chart.getRenderingHints();

            if (antiAlias) {
                rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); //fix
            } else {
                rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
                rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //fix
            }

//            svgGenerator.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//            svgGenerator.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
//            svgGenerator.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
//            svgGenerator.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
//            svgGenerator.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
//            svgGenerator.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            
            chart.draw(svgGenerator, new Rectangle2D.Double(0, 0, width, height), new ChartRenderingInfo());
            
            //undo anti-aliasing bugfix settings for chart to use correct settings:
            if (antiAlias) {
                rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            } else {
                rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
                rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
            }            
            
            final boolean useCSS = true;
            Writer out = null;
            try {
                out = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(new File(result), false)),"iso-8859-1"); //UTF-8
                svgGenerator.stream(out, useCSS);
            } finally {
                svgGenerator.dispose();
                IOUtils.close(out);
            }
        }//else: input unavailable
        
        return result;
    }//saveChartToSVG()
Java 11, JFreeChart 1.0.15, JFreeSVG 4.0

Zappo
Posts: 9
Joined: Thu Jan 31, 2008 8:53 pm

Post by Zappo » Wed Feb 13, 2008 5:14 pm

Thanks mhilpert, that's exactly the sort of thing I'm looking for. :)

I'll also keep looking for something to export to other formats (WMF/EMF and EPS have been specifically required by my client), but this is a nicely working solution.

Taqua
JFreeReport Project Leader
Posts: 698
Joined: Fri Mar 14, 2003 3:34 pm
Contact:

Post by Taqua » Wed Feb 13, 2008 8:00 pm

EPS might be supported by using FreeHEP.

However, I doubt that you will find a WMF exporter out there - as the WMF format is 100% undocumented and a living nightmare to work with. No sane developer would volunteer to write a WMF generator in Java, I guess :)

If you are working on Windows anyway, you might have more luck using a native SVG to WMF converter or so. If you feel very adventerous, you could even try to use the OpenOffice-SDK to convert from SVG into WMF. By using the UNO-Interfaces this should be relatively easy - but you will pay for it with a 400+ MB dependency to that office package.

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Post by paradoxoff » Wed Feb 13, 2008 8:48 pm

As announced....

Code: Select all

import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D;
import org.freehep.graphicsio.emf.EMFGraphics2D;
	public void saveAsEPS(JFreeChart chart,File outfile) throws Exception{
		OutputStream out = new java.io.FileOutputStream(outfile);
		EPSDocumentGraphics2D g2d = new EPSDocumentGraphics2D(false);
		g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
		int width = 600;
		int height = 400;
		g2d.setupDocument(out,width, height); //400pt x 200pt
		chart.draw(g2d,new Rectangle(width,height));
		g2d.finish();
		out.flush();
		out.close();
	}
	public void saveAsEMF(JFreeChart chart,File outfile) throws Exception{
		OutputStream out = new java.io.FileOutputStream(outfile);
		int width = 600;
		int height = 400;
		EMFGraphics2D g2d = new EMFGraphics2D(out,new Dimension(width,height));
		g2d.startExport();
		chart.draw((Graphics2D)g2d.create(),new Rectangle(width,height));
		g2d.endExport();
		g2d.closeStream();
	}
Required jars:
xmlgraphics-commons-1.2.jar (apache xml graphics common)
and several freehep-XXX- Jars. I am not sure which jars are the minimum requirement.
I have used the EMF export several times, and the files looked really like vector graphics. They can be imported into MSOffice and zoomed without loosing quality.
Regards, Paradoxoff

Zappo
Posts: 9
Joined: Thu Jan 31, 2008 8:53 pm

Post by Zappo » Fri Feb 15, 2008 12:37 pm

Thanks paradoxoff! :D
That works nice, and the same libraries also support a bunch of other formats. No transparency - I've tried setting up rendering hints, but they don't seem to change anything. No problem, it's not essential.

vimal
Posts: 8
Joined: Sat Jul 24, 2010 3:38 pm
antibot: No, of course not.

Re: Export to a vector format

Post by vimal » Sun Jul 25, 2010 11:28 am

saveAsEMF method throwing 'java.lang.ArrayIndexOutOfBoundsException: 4'.

Please help me.

Locked