1 package org.simantics.diagram.export;
\r
3 import java.awt.Graphics2D;
\r
4 import java.awt.Point;
\r
5 import java.awt.RenderingHints;
\r
6 import java.awt.geom.AffineTransform;
\r
7 import java.awt.geom.Rectangle2D;
\r
8 import java.awt.image.BufferedImage;
\r
11 import javax.imageio.ImageIO;
\r
13 import org.simantics.g2d.canvas.ICanvasContext;
\r
14 import org.simantics.g2d.diagram.DiagramHints;
\r
15 import org.simantics.g2d.diagram.DiagramUtils;
\r
16 import org.simantics.g2d.diagram.IDiagram;
\r
17 import org.simantics.g2d.participant.TransformUtil;
\r
18 import org.simantics.scenegraph.g2d.G2DRenderingHints;
\r
19 import org.simantics.scenegraph.utils.QualityHints;
\r
20 import org.simantics.utils.page.MarginUtils;
\r
22 public class ImageBuilder {
\r
31 * @param file File to write the image (optional)
\r
32 * @param dpi Dots Per Inch
\r
33 * @param size Image size in pixels
\r
34 * @param margin percentage of image width for margins. 0.05 is 5%.
\r
36 public ImageBuilder(File file, Double dpi, Point size, double margin) {
\r
40 this.margin = Math.max(margin,0.0);
\r
45 * @param canvasContext
\r
46 * the canvas context to paint
\r
47 * @param writeResults
\r
48 * <code>true</code> to actually write the resulting Image to the file.
\r
50 public BufferedImage paint(ICanvasContext canvasContext) throws Exception {
\r
52 Graphics2D g2 = null;
\r
53 BufferedImage image = null;
\r
55 IDiagram diagram = canvasContext.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);
\r
56 Rectangle2D diagramRect = DiagramUtils.getContentRect(diagram);
\r
58 if (diagramRect == null)
\r
59 diagramRect = new Rectangle2D.Double(0, 0, 100, 100);
\r
61 // add margins to content.
\r
62 double off = Math.max(diagramRect.getWidth(), diagramRect.getHeight()) * margin*0.5;
\r
63 diagramRect = new Rectangle2D.Double(diagramRect.getX() - off, diagramRect.getY() - off, diagramRect.getWidth() + off * 2.0, diagramRect.getHeight() + off * 2.0);
\r
65 // Make sure the transformation is reset.
\r
66 AffineTransform tr = new AffineTransform();
\r
68 Rectangle2D controlArea;
\r
70 double mmToInch = 1.0 / 25.0;
\r
71 controlArea = new Rectangle2D.Double(0, 0, diagramRect.getWidth() * mmToInch * dpi, diagramRect.getHeight() * mmToInch * dpi);
\r
74 controlArea = new Rectangle2D.Double(0, 0, size.getX(), size.getY());
\r
77 canvasContext.getSingleItem(TransformUtil.class).fitArea(controlArea, diagramRect, MarginUtils.NO_MARGINS);
\r
79 int width = (int) controlArea.getWidth();
\r
80 int height = (int) controlArea.getHeight();
\r
81 long sizeBytes = width*height*3;
\r
82 long free = Runtime.getRuntime().freeMemory();
\r
83 if (sizeBytes >= free) { // TODO: should we estimate memory required for rendering?
\r
85 free = Runtime.getRuntime().freeMemory();
\r
88 if (sizeBytes >= free) {
\r
89 throw new Exception("There is not enough available memory to create the image; required " + sizeBytes + ", available " + free);
\r
92 image = new BufferedImage(width, height , BufferedImage.TYPE_3BYTE_BGR);
\r
93 g2 = (Graphics2D) image.getGraphics();
\r
95 QualityHints.HIGH_QUALITY_HINTS.setQuality(g2);
\r
96 g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
\r
99 g2.setTransform(tr);
\r
100 g2.setClip(new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight()));
\r
102 g2.setRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS, new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight()));
\r
104 if (canvasContext.isLocked())
\r
105 throw new IllegalStateException("cannot render image, canvas context is locked: " + canvasContext);
\r
107 canvasContext.getSceneGraph().render(g2);
\r
109 if (file != null) {
\r
110 String name = file.getName();
\r
111 name = name.substring(name.lastIndexOf(".") + 1);
\r
112 ImageIO.write(image, name, file);
\r