package ie.dcu.segment.util; import ie.dcu.segment.annotate.*; import java.awt.*; import java.awt.image.*; import java.util.List; import org.eclipse.swt.graphics.Point; /** * Rasterize the annotations using the Graphics2D API. The annotations are drawn * onto a byte buffer, with one byte per pixel. * * @author Kevin McGuinness */ public class AnnotationRasterizer { private static final byte[] R = { (byte) 128, (byte) 255, (byte) 0 }; private static final byte[] G = { (byte) 128, (byte) 0, (byte) 0 }; private static final byte[] B = { (byte) 128, (byte) 0, (byte) 255 }; private static final Color[] COLORS = { new Color(128, 128, 128), new Color(255, 0, 0), new Color( 0, 0, 255) }; private static final ColorModel cm = new IndexColorModel(8,3,R,G,B); private final int width; private final int height; private final int npixels; private final WritableRaster wr; private final BufferedImage im; private transient byte[] buff; public AnnotationRasterizer(int width, int height) { this.width = width; this.height = height; this.npixels = width * height; this.wr = cm.createCompatibleWritableRaster(width, height); this.im = new BufferedImage(cm, wr, false, null); } public byte[] rasterize(AnnotationManager am) { paint(am); return getDataBuffer(); } private void paint(AnnotationManager am) { Graphics2D g = im.createGraphics(); // Clear background g.setColor(COLORS[0]); g.fillRect(0, 0, width, height); // For each annotation int lastWidth = -1; for (Annotation a : am.annotations()) { List pts = a.points(); // Skip empty if (pts.size() == 0) { continue; } // Check if we need to change the stroke int width = a.getLineWidth(); if (width != lastWidth) { g.setStroke(createStroke(width)); lastWidth = width; } // Set the color switch (a.getType()) { case Foreground: g.setColor(COLORS[1]); break; case Background: g.setColor(COLORS[2]); break; } // Paint the points if (pts.size() > 1) { Point last = null; for (Point p : pts) { if (last != null) { g.drawLine(last.x, last.y, p.x, p.y); } last = p; } } else { // If only one point Point p = pts.get(0); g.drawLine(p.x, p.y, p.x, p.y); } } // Commit changes g.dispose(); } private byte[] getDataBuffer() { // Optimize the typical case by avoiding a copy if unnecessary. DataBuffer buffer = wr.getDataBuffer(); if (buffer instanceof DataBufferByte) { // Good, we have a compatible data buffer DataBufferByte bytebuf = (DataBufferByte) buffer; int banks = bytebuf.getNumBanks(); if (banks == 1) { // Smashin, only one data bank is in use byte[] buff = bytebuf.getData(); // Sanity check if (buff.length == npixels) { return buff; } } } // Handle some unexpected data buffer by copying pixels if (buff == null) { buff = new byte[npixels]; } return (byte[]) wr.getDataElements(0, 0, width, height, buff); } private static final Stroke createStroke(int width) { return new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); } }