package fr.unistra.pelican.gui; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import javax.media.jai.*; import com.sun.media.jai.widget.DisplayJAI; import fr.unistra.pelican.ByteImage; /** The CustomDisplayJAI handles all the image traitments, including for the * background image and for the marker image. * * Thanks to the works of Allan Hanbury, Ilkka Luoma, Christophe Millet (SAIST) */ public class OldCustomDisplayJAI extends DisplayJAI { public static final int DEFAULT_BRUSH_SIZE = 5; public static final int MAX_BRUSH_SIZE = 100; public static final int MIN_BRUSH_SIZE = 1; private static final long serialVersionUID = 1L; /** The markers image. */ public TiledImage raster; /** Indice of the transparency of the markers (255 = completely visible). */ public int rasterTransparency = 255; /** The pen. */ public Stroke stroke; /** The pen's color. It's a 1-sized float array, wich only element is between [0;1]. * Precisely, it's a fraction of 255. */ public float color[]; /** X coordinate of the cursor's last position. */ private int xLast; /** Y coordinate of the cursor's last position. */ private int yLast; /** The color marker image (after the createColorMarkerImage process). */ private RenderedOp colorMarkerImage; /** Determines if the user is drawing or not. */ private boolean drawing = false; /** A lookup table associating all possible labels * with their color ( 1 eraser + 256 shades ) */ public int[][] colorMap = new int[257][4]; public double scaleFactor = 1.0; AffineTransform transform = new AffineTransform(); /** * Constructor * */ public OldCustomDisplayJAI() { super(); setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); // Initializes variables this.stroke = new BasicStroke( DEFAULT_BRUSH_SIZE ); // default pen color this.color = new float[1]; this.color[0] = (float) 1 / 256; } @Override public void set( RenderedImage im ) { this.set(im,null); } /** Method which sets the background image and creates the markers image based * on markers image passed in parameter, or on on dimension of the background image * if {tt}markers{/tt} equals to {tt}nil{/tt}. * @param im * @param markersImage */ public void set( RenderedImage im, ByteImage markersImage ) { super.set(im); // Create a marker image without an alpha channel this.raster = fr.unistra.pelican.util.Tools.createGrayImage( markersImage, im.getWidth(), im.getHeight() ); // repaint the component this.createColorMarkerImage(); this.repaint(); } /** * paintComponent method * @param g */ public void paintComponent(Graphics g) { // Paint the image in super class // super.paintComponent(g); ////////////// // Paint the image in super class // this is nearly the same instructions as in superclass, ... Graphics2D g2d = (Graphics2D)g; if ( source == null ) { g2d.setColor(getBackground()); g2d.fillRect(0, 0, getWidth(), getHeight()); return; } Insets insets = getInsets(); int tx = insets.left + originX; int ty = insets.top + originY; Rectangle clipBounds = g2d.getClipBounds(); g2d.setColor( getBackground() ); g2d.fillRect( clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height ); // ... but not that : I added it for zoom management AffineTransform tr = new AffineTransform( this.transform ); // Translation moves the entire image within the container tr.concatenate( AffineTransform.getTranslateInstance(tx,ty) ); g2d.drawRenderedImage( source,tr ); ////////////// if ( colorMarkerImage != null ) { // Get graphics and create GraphicsJAI Graphics2D g2d2 = (Graphics2D) g; GraphicsJAI gj = GraphicsJAI.createGraphicsJAI(g2d2, this); // Draw marker image gj.drawRenderedImage(colorMarkerImage, tr ); } } /** * Mouse pressed method * @param e */ public void mousePressed(MouseEvent e) { if ( e.getButton() == MouseEvent.BUTTON1 ) { if ( raster != null ) { this.drawing = true; this.xLast = e.getX(); this.yLast = e.getY(); Graphics2D g2d = this.raster.createGraphics(); // Set line width and marker (Alpha is 1.0, // because colorMap handles transparency) g2d.setStroke( this.stroke ); g2d.setColor( new Color( this.raster.getColorModel().getColorSpace(), this.color, 1.0f ) ); // Draw the line g2d.draw( new Line2D.Double( e.getX(),e.getY(), e.getX(),e.getY() ) ); // Update createColorMarkerImage(); // Repaint the component repaint(); } } } /** * Mouse dragged method * @param e */ public void mouseDragged(MouseEvent e) { if ( this.drawing == true ) { if ( this.raster != null ) { Graphics2D g2d = this.raster.createGraphics(); // Set line width and marker (Aplha is 1.0 this time, // because lut handels transparency) g2d.setStroke( this.stroke ); g2d.setColor( new Color( this.raster.getColorModel().getColorSpace(), this.color, 1.0f ) ); // Draw the line g2d.draw( new Line2D.Double( e.getX(),e.getY(), this.xLast,this.yLast ) ); // Update createColorMarkerImage(); // Repaint the component repaint(); this.xLast = e.getX(); this.yLast = e.getY(); } } } /** * Mouse released method * @param e */ public void mouseReleased(MouseEvent e) { if ( e.getButton() == MouseEvent.BUTTON1 ) this.drawing = false; } /** Initializes {@link #colorMarkerImage}. */ public void createColorMarkerImage() { byte[][] lut = new byte[4][256]; for ( int i = 0 ; i < 256 ; i++ ) { lut[0][i] = (byte) colorMap[i][0]; // reds lut[1][i] = (byte) colorMap[i][1]; // greens lut[2][i] = (byte) colorMap[i][2]; // blues lut[3][i] = (byte) colorMap[i][3]; // alphas } LookupTableJAI table = new LookupTableJAI(lut); ParameterBlock pb = new ParameterBlock(); pb.addSource( this.raster ); pb.add( table ); this.colorMarkerImage = JAI.create( "Lookup",pb,null ); } @Override public void setPreferredSize( Dimension preferredSize ) { super.setPreferredSize( preferredSize ); this.transform.scale( scaleFactor,scaleFactor ); repaint(); } }