/* * Copyright (C) 2004 The Concord Consortium, Inc., * 10 Concord Crossing, Concord, MA 01742 * * Web Site: http://www.concord.org * Email: info@concord.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * END LICENSE */ /** * Last modification information: * $Revision: 1.1 $ * $Date: 2011-02-18 13:39:35 $ * $Author: moll $ * * Copyright 2004 The Concord Consortium */ package org.concord.swing.util; import java.awt.Component; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Hashtable; import javax.swing.JComponent; import javax.swing.JPanel; /** * A class that takes a screen shot of a Component * and saves it as a jpg, png or gif image * @author Ingrid Moncada<p> * $Revision: 1.1 $ */ public class ComponentScreenshot { static private Hashtable extImageWriters = new Hashtable(); public static void registerImageWriter(String type, ImageWriter writer) { extImageWriters.put(type, writer); } public static void saveImageAsFile(BufferedImage image, String filename) throws Throwable { saveImageAsFile(image, filename, ""); } public static void saveImageAsFile(BufferedImage image, String filename, String type) throws Throwable { try{ File file = new File(filename); saveImageAsFile(image, file, type); }catch(Throwable e){ e.printStackTrace(); throw e; } } public static void saveImageAsFile(BufferedImage image, File file, String type) throws Throwable { FileOutputStream fos; fos = new FileOutputStream(file); if (type==null || type.equals("")){ saveImageAsOutputStream(image, fos); } else{ saveImageAsOutputStream(image, fos, type); } fos.close(); } /** * Saves the image in the output stream in the "best" format */ public static void saveImageAsOutputStream(BufferedImage image, OutputStream out) throws Throwable { //Try to save it as .png first try{ saveImageAsOutputStream(image, out, "png"); }catch(Throwable e){ //If it fails, try to save it as .gif saveImageAsOutputStream(image, out, "gif"); } } /** * Saves the image in the output stream in the given format */ public static void saveImageAsOutputStream(BufferedImage image, OutputStream out, String type) throws Throwable { try{ ImageWriter writer = (ImageWriter)extImageWriters.get(type); if(writer != null) { writer.write(image, type, out); } else { // To keep clear compatibility with java 1.3 Class clazz = Class.forName("javax.imageio.ImageIO"); Method m = clazz.getMethod("write",new Class[]{Class.forName("java.awt.image.RenderedImage"),String.class,java.io.OutputStream.class}); m.invoke(null,new Object[]{image,type,out}); } }catch(Throwable e){ e.printStackTrace(); throw e; } } public static void saveScreenshotAsImageFile(Component c, String filename, String type) throws Throwable { BufferedImage image = getScreenshot(c); saveImageAsFile(image, filename, type); } public static BufferedImage getScreenshot(Component c) throws Exception { return getScreenshot(c,false); } public static BufferedImage getScreenshot(Component comp, boolean includeParents) throws Exception { Component c; c = comp; if (includeParents){ //Hack? while (c.getParent()!=null && c.getParent() instanceof JPanel){ c = c.getParent(); } } return makeComponentImage(c, 1, 1); } /** * Given a graphics context and a component. Paint this component * on the graphics context. This handles issues of dobule buffering * without resizing or invalidating the component. * * @param g * @param c * @param xScale * @param yScale */ public static void paintScaledComponent(Graphics2D g, Component c, float xScale, float yScale) { g.scale(xScale, yScale); if(c instanceof JComponent){ JComponent jComp = (JComponent)c; boolean dBuffered = jComp.isDoubleBuffered(); // Double buffering must be turned off otherwise the paint method // just copies the buffered image which causes pixelation. // With buffering off the Graphics2D methods like drawLine, drawText // are called so the resulting lines and fonts are hi-res jComp.setDoubleBuffered(false); jComp.paint(g); jComp.setDoubleBuffered(dBuffered); } else { c.paint(g); } } /** * Create a buffered image that disregards any alpha settings * * @param c * @param xScale * @param yScale * @return * @throws Exception */ public static BufferedImage makeComponentImage(Component c, float xScale, float yScale) throws Exception { BufferedImage image = null; try{ image = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_RGB); // Create a graphics contents on the buffered image Graphics2D g = image.createGraphics(); paintScaledComponent(g,c,xScale,yScale); g.dispose(); }catch(Exception e){ e.printStackTrace(); throw e; } return image; } /** * Slightly modified version of Dima's screen shot * @param compForPicture * @param xScale * @param yScale * @return */ public static BufferedImage makeComponentImageAlpha(Component compForPicture, float xScale, float yScale) throws Exception { Object bim = null; Class clazz = Class.forName("java.awt.GraphicsEnvironment"); Method m = clazz.getMethod("getLocalGraphicsEnvironment",null); Object ge = m.invoke(null,null); m = clazz.getMethod("getDefaultScreenDevice",null); Object gd = m.invoke(ge,null); m = gd.getClass().getMethod("getDefaultConfiguration",null); Object gc = m.invoke(gd,null); m = gc.getClass().getMethod("getColorModel",null); java.awt.image.ColorModel cm = (java.awt.image.ColorModel)m.invoke(gc,null); boolean hasAlpha = cm.hasAlpha(); int cw = compForPicture.getSize().width; int ch = compForPicture.getSize().height; int bw = (int)(cw * xScale); int bh = (int)(ch * yScale); if(hasAlpha){ m = gc.getClass().getMethod("createCompatibleImage",new Class[]{int.class,int.class}); bim = m.invoke(gc,new Object[]{new Integer(bw),new Integer(bh)}); }else{ clazz = Class.forName("java.awt.image.BufferedImage"); Constructor c = clazz.getConstructor(new Class[]{int.class,int.class,int.class}); Field f = clazz.getField("TYPE_INT_ARGB"); int imageType = f.getInt(null); bim = c.newInstance(new Object[]{new Integer(bw),new Integer(bh),new Integer(imageType)}); } if(bim == null) { return null; } m = bim.getClass().getMethod("createGraphics",null); java.awt.Graphics2D og = (java.awt.Graphics2D)m.invoke(bim,null); paintScaledComponent(og, compForPicture, xScale, yScale); og.dispose(); return (BufferedImage)bim; /* * Older version of non reflected code java.awt.image.BufferedImage bim = null; java.awt.GraphicsEnvironment ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(); java.awt.GraphicsDevice gd = ge.getDefaultScreenDevice(); java.awt.GraphicsConfiguration.java gc = gd.getDefaultConfiguration(); boolean hasAlpha = gc.getColorModel().hasAlpha(); if(hasAlpha){ bim = gc.createCompatibleImage(compForPicture.getSize().width,compForPicture.getSize().height); }else{ bim = new java.awt.image.BufferedImage(compForPicture.getSize().width,compForPicture.getSize().height,java.awt.image.BufferedImage.TYPE_INT_ARGB); } if(bim == null) return; java.awt.Graphics og = bim.getGraphics(); compForPicture.paint(og); og.dispose(); java.io.FileOutputStream fos = new java.io.FileOutputStream(fileToSave); javax.imageio.ImageIO.write(bim,"png",fos); fos.close(); */ /* * older version using jimi java.awt.Image img = compForPicture.createImage(compForPicture.getSize().width,compForPicture.getSize().height); java.awt.Graphics og = img.getGraphics(); compForPicture.paint(og); java.awt.image.ImageProducer ip =img.getSource(); javax.imageio.ImageIO.write(bim,fileExtension,fos); com.sun.jimi.core.JimiImage jimiimage = com.sun.jimi.core.Jimi.createRasterImage(ip); com.sun.jimi.core.encoder.png.PNGEncoder pngencoder = new com.sun.jimi.core.encoder.png.PNGEncoder(); java.io.FileOutputStream fos = new java.io.FileOutputStream(fileToSave); pngencoder .encodeImage(jimiimage,fos); fos.close(); og.dispose(); */ } }