001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2022, by David Gilbert. All rights reserved. 006 * 007 * https://github.com/jfree/orson-charts 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package org.jfree.chart3d.export; 034 035import java.awt.Graphics2D; 036import java.awt.Rectangle; 037import java.awt.geom.Rectangle2D; 038import java.awt.image.BufferedImage; 039import java.io.BufferedOutputStream; 040import java.io.File; 041import java.io.FileNotFoundException; 042import java.io.FileOutputStream; 043import java.io.IOException; 044import java.io.OutputStream; 045import java.lang.reflect.Constructor; 046import java.lang.reflect.InvocationTargetException; 047import java.lang.reflect.Method; 048import javax.imageio.ImageIO; 049import org.jfree.chart3d.graphics3d.Drawable3D; 050import org.jfree.chart3d.graphics3d.RenderingInfo; 051import org.jfree.chart3d.internal.Args; 052 053/** 054 * Export utility methods. 055 * 056 * @since 1.4 057 */ 058public class ExportUtils { 059 060 /** 061 * Writes the current content to the specified file in SVG format. This 062 * will only work when the JFreeSVG library is found on the classpath. 063 * Reflection is used to ensure there is no compile-time dependency on 064 * JFreeSVG. Any exceptions that occur while writing the file are 065 * caught and wrapped in a {@code RuntimeException} that is then thrown. 066 * 067 * @param drawable the drawable ({@code null} not permitted). 068 * @param w the chart width. 069 * @param h the chart height. 070 * @param file the output file ({@code null} not permitted). 071 * 072 * @return The rendering info. 073 */ 074 public static RenderingInfo writeAsSVG(Drawable3D drawable, int w, int h, 075 File file) { 076 if (!ExportFormats.isJFreeSVGAvailable()) { 077 throw new IllegalStateException( 078 "JFreeSVG is not present on the classpath."); 079 } 080 Args.nullNotPermitted(drawable, "drawable"); 081 Args.nullNotPermitted(file, "file"); 082 try { 083 Class<?> svg2Class = Class.forName( 084 "org.jfree.svg.SVGGraphics2D"); 085 Constructor<?> c1 = svg2Class.getConstructor(double.class, double.class); 086 Graphics2D svg2 = (Graphics2D) c1.newInstance(w, h); 087 Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h); 088 RenderingInfo info = drawable.draw(svg2, drawArea); 089 Class<?> svgUtilsClass = Class.forName( 090 "org.jfree.svg.SVGUtils"); 091 Method m1 = svg2Class.getMethod("getSVGElement", (Class[]) null); 092 String element = (String) m1.invoke(svg2, (Object[]) null); 093 Method m2 = svgUtilsClass.getMethod("writeToSVG", File.class, 094 String.class); 095 m2.invoke(svgUtilsClass, file, element); 096 return info; 097 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException 098 | NoSuchMethodException | SecurityException | IllegalArgumentException 099 | InvocationTargetException ex) { 100 throw new RuntimeException(ex); 101 } 102 } 103 104 /** 105 * Writes a {@link Drawable3D} to the specified file in PDF format. This 106 * will only work when the OrsonPDF library is found on the classpath. 107 * Reflection is used to ensure there is no compile-time dependency on 108 * OrsonPDF. Any exceptions that occur while writing the file are 109 * caught and wrapped in a {@code RuntimeException} that is then thrown. 110 * 111 * @param drawable the drawable ({code null} not permitted). 112 * @param w the chart width. 113 * @param h the chart height. 114 * @param file the output file ({code null} not permitted). 115 * 116 * @return The rendering info. 117 */ 118 public static RenderingInfo writeAsPDF(Drawable3D drawable, int w, int h, 119 File file) { 120 if (!ExportFormats.isJFreePDFAvailable()) { 121 throw new IllegalStateException( 122 "JFreePDF is not present on the classpath."); 123 } 124 Args.nullNotPermitted(drawable, "drawable"); 125 Args.nullNotPermitted(file, "file"); 126 try { 127 Class<?> pdfDocClass = Class.forName("org.jfree.pdf.PDFDocument"); 128 Object pdfDoc = pdfDocClass.getDeclaredConstructor().newInstance(); 129 Method m = pdfDocClass.getMethod("createPage", Rectangle2D.class); 130 Rectangle2D rect = new Rectangle(w, h); 131 Object page = m.invoke(pdfDoc, rect); 132 Method m2 = page.getClass().getMethod("getGraphics2D"); 133 Graphics2D g2 = (Graphics2D) m2.invoke(page); 134 Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h); 135 RenderingInfo info = drawable.draw(g2, drawArea); 136 Method m3 = pdfDocClass.getMethod("writeToFile", File.class); 137 m3.invoke(pdfDoc, file); 138 return info; 139 } catch (ClassNotFoundException | InstantiationException ex) { 140 throw new RuntimeException(ex); 141 } catch (IllegalAccessException ex) { 142 throw new RuntimeException(ex); 143 } catch (NoSuchMethodException ex) { 144 throw new RuntimeException(ex); 145 } catch (SecurityException ex) { 146 throw new RuntimeException(ex); 147 } catch (IllegalArgumentException ex) { 148 throw new RuntimeException(ex); 149 } catch (InvocationTargetException ex) { 150 throw new RuntimeException(ex); 151 } 152 } 153 154 /** 155 * Writes the current content to the specified file in PNG format. 156 * 157 * @param drawable the drawable ({@code null} not permitted). 158 * @param w the chart width. 159 * @param h the chart height. 160 * @param file the output file ({@code null} not permitted). 161 * 162 * @return The rendering info. 163 * 164 * @throws FileNotFoundException if the file is not found. 165 * @throws IOException if there is an I/O problem. 166 */ 167 public static RenderingInfo writeAsPNG(Drawable3D drawable, int w, int h, 168 File file) throws FileNotFoundException, IOException { 169 BufferedImage image = new BufferedImage(w, h, 170 BufferedImage.TYPE_INT_ARGB); 171 Graphics2D g2 = image.createGraphics(); 172 RenderingInfo result = drawable.draw(g2, new Rectangle(w, h)); 173 OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 174 try { 175 ImageIO.write(image, "png", out); 176 } 177 finally { 178 out.close(); 179 } 180 return result; 181 } 182 183 /** 184 * Writes the current content to the specified file in JPEG format. 185 * 186 * @param drawable the drawable ({@code null} not permitted). 187 * @param w the chart width. 188 * @param h the chart height. 189 * @param file the output file ({@code null} not permitted). 190 * 191 * @return The rendering info. 192 * 193 * @throws FileNotFoundException if the file is not found. 194 * @throws IOException if there is an I/O problem. 195 */ 196 public static RenderingInfo writeAsJPEG(Drawable3D drawable, int w, int h, 197 File file) throws FileNotFoundException, IOException { 198 BufferedImage image = new BufferedImage(w, h, 199 BufferedImage.TYPE_INT_RGB); 200 Graphics2D g2 = image.createGraphics(); 201 RenderingInfo result = drawable.draw(g2, new Rectangle(w, h)); 202 OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 203 try { 204 ImageIO.write(image, "jpg", out); 205 } 206 finally { 207 out.close(); 208 } 209 return result; 210 } 211 212}