/** * */ package cz.cuni.mff.peckam.java.origamist.services; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import javax.media.j3d.Canvas3D; import javax.media.j3d.ImageComponent2D; import javax.media.j3d.Screen3D; import com.sun.j3d.utils.universe.SimpleUniverse; import cz.cuni.mff.peckam.java.origamist.gui.common.StepViewingCanvasController; import cz.cuni.mff.peckam.java.origamist.model.Origami; import cz.cuni.mff.peckam.java.origamist.model.Step; /** * A generator of step thumbnails. * * @author Martin Pecka */ public class StepThumbnailGenerator extends Service { /** The last set origami. */ protected Origami origami = null; /** The last set width and height. */ protected int width = 0, height = 0; /** The canvas this class uses for rendering. */ protected final Canvas3D canvas; /** The canvas controller controlling this.canvas. */ protected final StepViewingCanvasController controller; /** The callback that calls this.notify after the step has been completely set. */ protected final Runnable afterSetCallback; /** If true, a rendering has taken place since the creation of this class. */ protected boolean hasRendered = false; /** * A generator of step thumbnails. */ public StepThumbnailGenerator() { canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration(), true); controller = new StepViewingCanvasController(canvas); afterSetCallback = new Runnable() { @Override public void run() { controller.adjustSize(); synchronized (StepThumbnailGenerator.this) { StepThumbnailGenerator.this.notify(); } } }; // screen dimensions need to be set before rendering SimpleUniverse u = new SimpleUniverse(new Canvas3D(SimpleUniverse.getPreferredConfiguration())); Screen3D screen = u.getViewer().getCanvas3D().getScreen3D(); Screen3D screen2 = canvas.getScreen3D(); screen2.setSize(screen.getSize()); screen2.setPhysicalScreenWidth(screen.getPhysicalScreenWidth()); screen2.setPhysicalScreenHeight(screen.getPhysicalScreenHeight()); } /** * Get the thumbnail of the last step of the given origami. The thumbnail will have the given dimension and * background drawn. * * @param origami The origami the step is part of. * @param width Width of the thumbnail in px. * @param height Height of the thumbnail in px. * @return The thumbnail. */ public Image getThumbnail(Origami origami, int width, int height) { return getThumbnail(origami, origami.getModel().getSteps().getStep().get(origami.getModel().getSteps().getStep().size() - 1), width, height); } /** * Get the thumbnail of the step of the given origami. The thumbnail will have the given dimension and background * drawn. * * @param origami The origami the step is part of. * @param step The step to render. * @param width Width of the thumbnail in px. * @param height Height of the thumbnail in px. * @return The thumbnail. */ public Image getThumbnail(Origami origami, Step step, int width, int height) { return getThumbnail(origami, step, width, height, true); } /** * Get the thumbnail of the step of the given origami. The thumbnail will have the given dimension. * * @param origami The origami the step is part of. * @param step The step to render. * @param width Width of the thumbnail in px. * @param height Height of the thumbnail in px. * @param withBackground If true, draw the background color instead of transparent pixels. * @return The thumbnail. */ public Image getThumbnail(Origami origami, Step step, int width, int height, boolean withBackground) { if (this.origami != origami) { this.origami = origami; canvas.setBackground(origami.getPaper().getBackgroundColor()); controller.setOrigami(origami); } if (this.width != width || this.height != height) { ImageComponent2D image = new ImageComponent2D(ImageComponent2D.FORMAT_RGBA8, width, height); canvas.setOffScreenBuffer(image); this.width = width; this.height = height; } if (!hasRendered) { canvas.renderOffScreenBuffer(); // needed to make some transforms up-to-date hasRendered = true; } controller.setStep(step, afterSetCallback); synchronized (this) { try { wait(60000); } catch (InterruptedException e1) {} } canvas.waitForOffScreenRendering(); canvas.renderOffScreenBuffer(); canvas.waitForOffScreenRendering(); if (withBackground) { BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = result.createGraphics(); g.drawImage(canvas.getOffScreenBuffer().getImage(), 0, 0, canvas.getBackground(), null); return result; } else { return canvas.getOffScreenBuffer().getImage(); } } }