CustomCanvasOJ.java :  » Image » objectj » oj » graphics » Java Open Source

Java Open Source » Image » objectj 
objectj » oj » graphics » CustomCanvasOJ.java
/*
 * CustomCanvasOJ.java
 * fully documented on 15.3.2010
 *
 * extends ImageCanvas to append routines for drawing markers after
 * ImageJ is finished with drawing the image
 */
package oj.graphics;

import ij.CompositeImage;
import ij.IJ;
import ij.ImagePlus;
import ij.Macro;
import ij.gui.ImageCanvas;
import ij.macro.Interpreter;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.image.BufferStrategy;
import oj.OJ;
import oj.project.CellOJ;
import oj.project.DataOJ;
import oj.project.ImageOJ;
import oj.project.YtemOJ;
import oj.project.YtemDefOJ;
import oj.gui.KeyEventManagerOJ;
import oj.processor.ToolStateProcessorOJ;
import oj.processor.events.CellChangedEventOJ;
import oj.processor.events.CellChangedListenerOJ;
import oj.processor.events.YtemChangedEventOJ;
import oj.processor.events.YtemChangedListenerOJ;
import oj.processor.events.YtemDefChangedEventOJ;
import oj.processor.EventProcessorOJ;
import oj.processor.events.DrawCellEventOJ;
import oj.processor.events.DrawCellListenerOJ;
import oj.processor.events.YtemDefChangedListenerOJ;
import oj.project.YtemDefsOJ;

public class CustomCanvasOJ extends ImageCanvas implements DrawCellListenerOJ, CellChangedListenerOJ, YtemChangedListenerOJ, YtemDefChangedListenerOJ {

  public static int hits = 0;
  public static final int MARKER_L = 2;
  public static final int MARKER_R = 2;
  public static final int MARKER_SIZE = 4;
  public static final int markerL = MARKER_L + 0;
  public static final int markerR = MARKER_R + 0;
  public static final int markerSize = MARKER_SIZE + 0;
  //public static final int MARKER_CHECK_AREA = 10;
  private String imageName;
  private DataOJ dataOJ;
  private ImageOJ image;
  public BufferStrategy buforowanie;
  private Font fontArial = Font.decode("Arial-11");
  private Font fontArialItalic = Font.decode("Arial-ITALIC-11");
  //for offscreen trial 3.2.2011
  private Image offScreenImage;
  private int offScreenWidth = 0;
  private int offScreenHeight = 0;

  //called by applyImageGraphics
  public CustomCanvasOJ(ImagePlus imp, DataOJ dataOJ, String imageName) {
    super(imp);
    this.dataOJ = dataOJ;
    this.imageName = imageName;

    addKeyListener(KeyEventManagerOJ.getInstance());

    image = dataOJ.getImages().getImageByName(imageName);

    OJ.getEventProcessor().addYtemDefChangedListener(this);
    OJ.getEventProcessor().addYtemChangedListener(this);
    OJ.getEventProcessor().addCellChangedListener(this);
    OJ.getEventProcessor().addDrawCellListener(this);
    OJ.getEventProcessor().updateMarkers = true;//10.2.2011
    requestFocus();
  }

  @Override
  public void addNotify() {
    super.addNotify();
  }

  /**
   * repaints image if cell has changed
   */
  public void drawCell(DrawCellEventOJ evt) {
    if (imp == null) {
      return;//3. 3. 2009
    } else if (imp.getWindow() == null) {
      return;//28.3.2009
    } else if (imp.getWindow().isVisible() /*&& batchFilter()*/) {//6.2.2011
      repaint();
    }
  }

  public void cellChanged(CellChangedEventOJ evt) {
    if (imp == null) {
      return;//3. 3. 2009
    } else if (imp.getWindow() == null) {
      return;//28.3.2009
    } else if (imp.getWindow().isVisible() /*&& batchFilter()*/) {//6.2.2011
      repaint();
    }
  }

  boolean batchFilter() {

    if (Macro.getOptions() != null && Interpreter.isBatchMode()) {
      return false;
    } else {
      return true;
    }
  }

  /**
   * repaints image if ytem has changed
   */
  public void ytemChanged(YtemChangedEventOJ evt) {
    if (imp == null) {
      return;
    } else if (imp.getWindow() == null) {
      return;
    } else if (imp.getWindow().isVisible()/* && batchFilter()*/) {//6.2.2011
      repaint();
    }
  }

  public String getImageName() {
    return imageName;
  }

  /**
   * first ImageJ repaints image, then markers are superimposed
   */
//  public void paintOld(Graphics g) {
//    super.paint(g);
//    drawOverlayoj(g);
//  }
  @Override
  public void resetDoubleBuffer() {
    super.resetDoubleBuffer();
    offScreenImage = null;

  }

  @Override
  //first create an offscreen image, then pass it to ImageJ-Canvas
  //then add my own drawing,
  //then take the original graphport and draw the complete offscreen image onto it.
  // problem: the entire image is
  public void paint(Graphics g) {
    hits++;
    if (!IJ.isWindows() || !OJ.doubleBuffered) {
      super.paint(g);
      drawOverlayoj(g);

    } else {
      Graphics g2 = getOffscreenGraphics();//3.2.2011
      super.paint(g2);
      drawOverlayoj(g2);
      g.drawImage(offScreenImage, 0, 0, null);
    }
  }

  Graphics getOffscreenGraphics() {
    final int srcRectWidthMag = (int) (srcRect.width * magnification);
    final int srcRectHeightMag = (int) (srcRect.height * magnification);
    if (offScreenImage == null || offScreenWidth != srcRectWidthMag || offScreenHeight != srcRectHeightMag) {
      offScreenImage = createImage(srcRectWidthMag, srcRectHeightMag);
      offScreenWidth = srcRectWidthMag;
      offScreenHeight = srcRectHeightMag;
    }
    return offScreenImage.getGraphics();
  }

  /**
   * offscreen to screen coordinate conversion
   */
  public int screenX(double x, double magnification) {
    return (int) Math.round((x - srcRect.x) * magnification);
  }

  /**
   * offscreen to screen coordinate conversion
   */
  public int screenY(double y, double magnification) {
    return (int) Math.round((y - srcRect.y) * magnification);
  }

  /**
   * screen to offscreen coordinate conversion
   */
  public double offScreenX(int x, double magnification) {
    return srcRect.x + x / magnification;
  }

  /**
   * screen to offscreen coordinate conversion
   */
  public double offScreenY(int y, double magnification) {
    return srcRect.y + y / magnification;
  }

  /**
   * Don't switch to ImageJ's cursors when an ObjectJ tool is selected (except the hand tool)
   */
  @Override
  public void setCursor(int sx, int sy, int ox, int oy) {
    if (!OJ.isProjectOpen) {
      return;
    }
    if ((!IJ.spaceBarDown()) && (OJ.getToolStateProcessor().getToolState() != ToolStateProcessorOJ.STATE_NONE)) {
      //ImageCanvas uses these values as result for getCursorLocation function
      xMouse = ox;
      yMouse = oy;
    } else {
      super.setCursor(sx, sy, ox, oy);
    }
  }

  /**
   * ---
   */
  public void updateCanvas(ImageCanvas ic, ImagePlus imp) {
    if (ic == null || ic == this || imp == null) {
      return;
    }
    if (imp.getWidth() != imageWidth || imp.getHeight() != imageHeight) {
      return;
    }
    srcRect = new Rectangle(ic.getSrcRect().x, ic.getSrcRect().y, ic.getSrcRect().width, ic.getSrcRect().height);
    setMagnification(ic.getMagnification());
    setDrawingSize(ic.getPreferredSize().width, ic.getPreferredSize().height);
  }

  public void setSrcRect(int x, int y, int w, int h) {//n_ 26.3.2008
    this.srcRect.setBounds(x, y, w, h);
  }

  /**
   * calculates channel from stackindex (former slice number) (1-based)
   */
  public static int getChannel(ImagePlus imp, int stackIndex) {
    int[] dim = imp.getDimensions();//{width, height, nChannels, nSlices, nFrames}
    return ((stackIndex - 1) % dim[2]) + 1;
  }

  /**
   * calculates z-slice number from stackindex (1-based)
   */
  public static int getSlice(ImagePlus imp, int stackIndex) {
    int[] dim = imp.getDimensions();
    return (((stackIndex - 1) / dim[2]) % dim[3]) + 1;
  }

  /**
   * calculates frame number from stackindex (1-based)
   */
  public static int getFrame(ImagePlus imp, int stackIndex) {
    int[] dim = imp.getDimensions();
    return (((stackIndex - 1) / (dim[2] * dim[3])) % dim[4]) + 1;
  }

  /**
   * returns true if channel content is visible- even though it may be blended with others
   */
  public static boolean isActiveChannel(ImagePlus imp, int channel) {
    boolean[] active = ((CompositeImage) imp).getActiveChannels();
    return active[channel];
  }

  /**
   * Draws non-destructive markers
   */
  void drawOverlayoj(Graphics g) {
    boolean allvisible = true;
    YtemDefsOJ ytemDefs = OJ.getData().getYtemDefs();
    if (ytemDefs != null) {
      allvisible = ytemDefs.isCellLayerVisible();
    }

    //       if (OJ.getData().getYtemDefs().isCellLayerVisible()) {
    if (allvisible) {
      int visRangeHigh = OJ.getData().getYtemDefs().getVisRangeHigh();//28.1.2009
      int visRangeLow = OJ.getData().getYtemDefs().getVisRangeLow();
      FontRenderContext frc = ((Graphics2D) g).getFontRenderContext();
      Rectangle rectangle = getSrcRect();
      double magnif = getMagnification();
      int firstCell = image.getFirstCell();
      int lastCell = image.getLastCell();
      int imageStackIndex = imp.getCurrentSlice();
      boolean show_cell_number = dataOJ.getYtemDefs().getShowCellNumber();
      int nCells = dataOJ.getCells().getCellsCount();
      if ((firstCell >= 0) && (lastCell >= firstCell)) {
        for (int i = firstCell; i <= lastCell; i++) {
          boolean inRange = (i >= 0 && i < nCells);//14.11.2008
          if (!inRange) {
            IJ.log("Range error: index=" + i + "  nCells=" + nCells);
          }
          if (inRange) {
            CellOJ cell = dataOJ.getCells().getCellByIndex(i);
            int ytemsCount = cell.getYtemsCount();
            for (int ytemNo = 0; ytemNo < ytemsCount; ytemNo++) {
              YtemOJ ytem = cell.getYtemByIndex(ytemNo);
              int homeSlice = ytem.getStackIndex();//+++exception NullPointerException
              if (homeSlice == 0) {
                homeSlice = cell.getStackIndex();
              }
              if ((imp instanceof CompositeImage) && (((CompositeImage) imp).getMode() == CompositeImage.COMPOSITE)) {
                int channel = getChannel(imp, homeSlice);
                int slice = getSlice(imp, homeSlice);
                int frame = getFrame(imp, homeSlice);
                if (!isActiveChannel(imp, channel - 1)) {
                  continue;
                }
                if ((slice != imp.getSlice()) || (frame != imp.getFrame())) {
                  continue;
                }
              } else {
                int upperLimit = homeSlice + visRangeHigh;
                if (visRangeHigh == -1) {
                  upperLimit = Integer.MAX_VALUE;
                }
                int lowerLimit = homeSlice - visRangeLow;
                if (visRangeLow == -1) {
                  lowerLimit = 0;
                }

                boolean visible = (imageStackIndex >= lowerLimit) && (imageStackIndex <= upperLimit);//28.1.2009

                if (!visible) {
                  continue;
                }
              }
              YtemDefOJ ydef = dataOJ.getYtemDefs().getYtemDefByName(ytem.getYtemDef());
              if ((ydef != null) && ydef.isVisible()) {
                int ydefType = ydef.getLineType();
                g.setColor(ydef.getLineColor());
                double line_width = 1.0;
                switch (ydefType) {
                  case YtemDefOJ.LINE_TYPE_ZEROPT:
                    line_width = 0;
                    break;
                  case YtemDefOJ.LINE_TYPE_TWOPT:
                    line_width = 2.0;
                    break;
                  case YtemDefOJ.LINE_TYPE_THREEPT:
                    line_width = 3.0;
                    break;
                }
                if (ydefType == YtemDefOJ.LINE_TYPE_DOTTED) {
                  float[] dash = new float[]{3, 3};
                  ((Graphics2D) g).setStroke(new BasicStroke((float) line_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0, dash, 0));
                } else if (ydefType == YtemDefOJ.LINE_TYPE_LIGHT_DOTTED) {
                  float[] dash = new float[]{3, 5};
                  ((Graphics2D) g).setStroke(new BasicStroke((float) line_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0, dash, 0));
                } else {
                  ((Graphics2D) g).setStroke(new BasicStroke((float) line_width));
                }

                int[] x_array;
                int[] y_array;
                if (!((magnif == 1.0 && rectangle.x == 0 && rectangle.y == 0))) {
                  x_array = ytem.toXArray(rectangle.x, magnif);
                  y_array = ytem.toYArray(rectangle.y, magnif);
                } else {
                  x_array = ytem.toXArray();
                  y_array = ytem.toYArray();
                }

                if (x_array.length > 0) {
                  switch (ytem.getType()) {
                    case YtemDefOJ.YTEM_TYPE_SEGLINE:
                    case YtemDefOJ.YTEM_TYPE_LINE:
                    case YtemDefOJ.YTEM_TYPE_ANGLE:
                      if (ydefType != YtemDefOJ.LINE_TYPE_ZEROPT) {
                        g.drawPolyline(x_array, y_array, x_array.length);
                      }
                      break;
                    case YtemDefOJ.YTEM_TYPE_POLYGON:
                    case YtemDefOJ.YTEM_TYPE_ROI:
                      if (ydefType != YtemDefOJ.LINE_TYPE_ZEROPT) {



                        if (ytem.isOpen()) {
                          g.drawPolyline(x_array, y_array, x_array.length);//don't close shape while it is open, 8.7.2009
                        } else {
                          g.drawPolygon(x_array, y_array, x_array.length);
                        }
                      }
                      break;
                    default:
                  }

                  if (ytem.getType() != YtemDefOJ.YTEM_TYPE_ROI) {
                    for (int j = 0; j < x_array.length; j++) {
                      drawMarker((Graphics2D) g, x_array[j], y_array[j], ydef.getMarkerType(), cell.isSelected());
                    }
                  } else {
                    drawMarker((Graphics2D) g, x_array[0], y_array[0], ydef.getMarkerType(), cell.isSelected());
                  }
                }

                if (!EventProcessorOJ.BlockEventsOnDrag && (x_array.length > 0) && show_cell_number && (ytemNo == 0)) {
                  int x = x_array[0];
                  int y = y_array[0];
                  if (x < 8) {
                    x = x + 10;
                  } else {
                    x = x - 10;
                  }
                  if (y < 8) {
                    y = y + 10;
                  } else {
                    y = y - 4;
                  }
                  if (cell.isOpen()) {
                    if (cell.isQualified()) {
                      TextLayout layout = new TextLayout("*" + Integer.toString(i + 1) + "*", fontArialItalic, frc);//15.3.2010
                      layout.draw((Graphics2D) g, (float) x, (float) y);
                    } else {
                      g.setColor(Color.GRAY);
                      TextLayout layout = new TextLayout("{* " + Integer.toString(i + 1) + "}", fontArialItalic, frc);
                      layout.draw((Graphics2D) g, (float) x, (float) y);
                    }
                  } else {
                    if (cell.isQualified()) {
                      TextLayout layout = new TextLayout(Integer.toString(i + 1), fontArial, frc);
                      layout.draw((Graphics2D) g, (float) x, (float) y);
                    } else {
                      g.setColor(Color.LIGHT_GRAY);
                      TextLayout layout = new TextLayout("{" + Integer.toString(i + 1) + "}", fontArial, frc);
                      layout.draw((Graphics2D) g, (float) x, (float) y); //31.8.2009
                      g.setColor(Color.DARK_GRAY);
                      layout.draw((Graphics2D) g, (float) x + 1, (float) y);

                    }
                  }
                } else {
                  if (ytemNo == 0) {
                    // disabled 22.2.2009
                    //System.out.println(Integer.toString(i + 1) + "   " + Boolean.toString(EventProcessorOJ.BlockEventsOnDrag) + " " + Integer.toString(x_array.length) + "   " + Boolean.toString(show_cell_number));
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  /**
   * draws one of the marker types plus, square, cross, dot, pixel, diamond
   */
  private void drawMarker(Graphics2D g, int xpos, int ypos, int markerType, boolean selected) {
    if (selected) {
      g.fillRect(xpos - 3, ypos - 3, 7, 7);
    } else {
      ((Graphics2D) g).setStroke(new BasicStroke((float) 1.0));//n_12.6.2008
      switch (markerType) {
        case YtemDefOJ.MARKER_TYPE_CROSS:
          g.drawLine(xpos - markerL, ypos - markerL, xpos + markerR, ypos + markerR); //n_12.11.2006
          g.drawLine(xpos - markerL, ypos + markerL, xpos + markerR, ypos - markerR);
          break;
        case YtemDefOJ.MARKER_TYPE_DIAMOND:
          g.drawLine(xpos, ypos - markerL, xpos - markerL, ypos); //n_12.11.2006
          g.drawLine(xpos - markerL, ypos, xpos, ypos + markerR);
          g.drawLine(xpos, ypos + markerR, xpos + markerR, ypos);
          g.drawLine(xpos + markerR, ypos, xpos, ypos - markerL);
          break;
        case YtemDefOJ.MARKER_TYPE_DOT:
          g.fillRect(xpos - markerL, ypos - markerL, markerSize, markerSize); //n_12.11.2006
          break;
        case YtemDefOJ.MARKER_TYPE_PIXEL:
          g.drawLine(xpos, ypos, xpos, ypos);
          break;
        case YtemDefOJ.MARKER_TYPE_PLUS:
          g.drawLine(xpos, ypos - markerL, xpos, ypos + markerR); //n_12.11.2006
          g.drawLine(xpos - markerL, ypos, xpos + markerR, ypos);
          break;
        case YtemDefOJ.MARKER_TYPE_SQUARE:
          g.drawRect(xpos - markerL, ypos - markerL, markerSize, markerSize); //n_12.11.2006
          break;
        default:
          g.drawRect(xpos - markerL, ypos - markerL, markerSize, markerSize);
      }
    }
  }

  public void ytemDefChanged(YtemDefChangedEventOJ evt) {
    repaint();
  }
  //removed 15.3.2010 BasicStroke bs = new BasicStroke((float) 1.0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0, new float[]{2, 2}, 0);

  /** Zooms by zoomFactor, but doesn't touch  window size and position.
   * If possible, Pixel (x, y) is made to appear at top left.
   * If window is larger then zoomed content, which would result in
   * white borders, returns without action.
   */
  public void ojZoom(double zoomFactor, int x, int y) {

    int w = (int) Math.round(dstWidth / zoomFactor);
    if (w * zoomFactor < dstWidth) {
      w++;

    }
    int h = (int) Math.round(dstHeight / zoomFactor);
    if (h * zoomFactor < dstHeight) {
      h++;

    }
    if (w > imageWidth || h > imageHeight) {
      return;
    }
    Rectangle r = new Rectangle(x - w / 2, y - h / 2, w, h);//17.6.2009
    if (r.x < 0) {
      r.x = 0;
    }
    if (r.y < 0) {
      r.y = 0;
    }
    if (r.x + w > imageWidth) {
      r.x = imageWidth - w;
    }
    if (r.y + h > imageHeight) {
      r.y = imageHeight - h;
    }

    srcRect = r;
    setMagnification(zoomFactor);

    repaint();
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.