public IntensityPaint(ROI2D roi, Sequence seq, IcyCanvas canv) { canvas = canv; sequence = seq; guideRoi = roi; displayRectangle = new ROI2DRectangle( lastPoint.getX(), lastPoint.getY(), lastPoint.getX() + Math.min(800, sequence.getWidth() / 4), lastPoint.getY() + Math.min(800, sequence.getHeight() / 4)); displayRectangle.setName("(" + guideRoi.getName() + ")"); displayRectangle.setColor(guideRoi.getColor()); displayRectangle.setOpacity((float) 0.2); cursor1 = new Line2D.Double(); cursor2 = new Line2D.Double(); if (guideRoi.getClass().equals(ROI2DLine.class)) paintMode = PaintMode.line; else if (guideRoi.getClass().equals(ROI2DPoint.class)) paintMode = PaintMode.point; else paintMode = PaintMode.area; (new Thread(new computeRunnable())).start(); sequence.addListener(this); guideRoi.addListener(this); if (paintMode == PaintMode.line) canvas.getViewer().addListener(this); }
/** * Save the specified sequence in the specified file.<br> * If sequence contains severals images then file is used as a directory<br> * to store all single images. * * @param sequence sequence to save * @param file file where we want to save sequence */ public static void save(Sequence sequence, File file) { save( sequence, file, 0, sequence.getSizeZ() - 1, 0, sequence.getSizeT() - 1, 15, (sequence.getSizeZ() * sequence.getSizeT()) > 1, true); }
/** * Save the specified sequence in the specified file.<br> * When the sequence contains severals image the multiFile flag is used to indicate<br> * if images are saved in severals files (file then specify a directory) or in a single file. * * @param sequence sequence to save * @param file file where we want to save sequence * @param multipleFiles flag to indicate if images are saved in separate file * @param showProgress show progress bar */ public static void save( Sequence sequence, File file, boolean multipleFiles, boolean showProgress) { save( sequence, file, 0, sequence.getSizeZ() - 1, 0, sequence.getSizeT() - 1, 15, multipleFiles, showProgress); }
/** @deprecated Use {@link #save(Sequence, File, boolean, boolean)} instead. */ @Deprecated public static void save(Sequence sequence, File file, boolean multipleFiles) { save( sequence, file, 0, sequence.getSizeZ() - 1, 0, sequence.getSizeT() - 1, 15, multipleFiles, true); }
public void dispose() { try { sequence.removeListener(this); guideRoi.removeListener(this); canvas.getViewer().removeListener(this); } catch (Exception e) { } }
@Override public void sequenceChanged(SequenceEvent sequenceEvent) { if (sequenceEvent.getSource() == SequenceEvent.SequenceEventSourceType.SEQUENCE_DATA) { cancelCompute = true; while (computing) try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } (new Thread(new computeRunnable())).start(); } if (sequenceEvent.getSourceType() == SequenceEventSourceType.SEQUENCE_OVERLAY && sequenceEvent.getSource() == this && sequenceEvent.getType() == SequenceEventType.REMOVED) sequence.removeROI(displayRectangle); }
void drawHisto(ROI2D roi, Graphics2D g, Sequence sequence, final IcyCanvas canvas) { if (!roiPairDict.containsKey(roi)) return; IntensityPaint ip = roiPairDict.get(roi); String currentValueX = ""; String currentValueV = ""; String maxValue = ""; String minValue = ""; for (int component = 0; component < sequence.getSizeC(); component++) { AffineTransform originalTransform = g.getTransform(); g.setColor(new Color(236, 10, 170)); if (sequence.getSizeC() != 1) { if (component == 0) g.setColor(Color.red); if (component == 1) g.setColor(Color.green); if (component == 2) g.setColor(Color.blue); } Rectangle2D rectBox = ((ROI2DRectangle) ip.displayRectangle).getRectangle(); Rectangle2D polyBox = ip.drawPolygon[component].getBounds2D(); try { if (ip.paintMode == PaintMode.line) { Line2D line = ((ROI2DLine) roi).getLine(); Point2D Lp; Point2D Rp; if (line.getX2() > line.getX1()) { Lp = line.getP1(); Rp = line.getP2(); } else { Lp = line.getP2(); Rp = line.getP1(); } int pos; if (Math.min(line.getX1(), line.getX2()) >= cursorPos.x) pos = 0; else if (Math.max(line.getX1(), line.getX2()) <= cursorPos.x) pos = ip.dataCount; else { pos = (int) ((cursorPos.x - Lp.getX()) / (Rp.getX() - Lp.getX()) * ip.dataCount); try { currentValueX = String.format("X:%.1f", cursorPos.x); currentValueV += String.format("%.1f ", ip.dataArr.get(component)[pos]); } catch (Exception e2) { } } ip.cursor1.setLine(pos, 0, pos, polyBox.getHeight()); } else { int pos = (int) cursorPos.z; ip.cursor1.setLine(pos, 0, pos, polyBox.getHeight()); try { currentValueX = String.format("Z:%.1f", cursorPos.z); currentValueV += String.format("%.1f ", ip.dataArr.get(component)[pos]); } catch (Exception e2) { } } double sx = rectBox.getWidth() / polyBox.getWidth(); double sy = rectBox.getHeight() / polyBox.getHeight(); if (sx < 100 && sy < 100) { g.translate(rectBox.getMinX(), rectBox.getMaxY()); g.scale(sx, -sy); g.draw(ip.drawPolygon[component]); g.setColor(new Color(100, 100, 170)); g.draw(ip.cursor1); g.setColor(new Color(236, 10, 170)); } else { char[] c = "Exceeding display limit!".toCharArray(); g.drawChars(c, 0, c.length, (int) rectBox.getCenterX() - 10, (int) rectBox.getCenterY()); } } finally { g.setTransform(originalTransform); // min,max double xStart, xEnd; if (ip.paintMode == PaintMode.line) { Line2D line = ((ROI2DLine) roi).getLine(); Point2D Lp; Point2D Rp; if (line.getX2() > line.getX1()) { Lp = line.getP1(); Rp = line.getP2(); } else { Lp = line.getP2(); Rp = line.getP1(); } xStart = Lp.getX(); xEnd = Rp.getX(); int pos; double yp; if (Math.min(line.getX1(), line.getX2()) >= cursorPos.x) { pos = (int) Lp.getX(); yp = Lp.getY(); } else if (Math.max(line.getX1(), line.getX2()) <= cursorPos.x) { pos = (int) Rp.getX(); yp = Rp.getY(); } else { pos = (int) cursorPos.x; yp = (cursorPos.x - Lp.getX()) / (line.getX2() - line.getX1()) * (line.getY2() - line.getY1()) + Lp.getY(); } ip.cursor2.setLine(pos, yp + 10, pos, yp - 10); g.draw(ip.cursor2); } else { xStart = 0; xEnd = ip.dataCount; } maxValue += String.format("%.1f ", ip.maxData[component]); minValue += String.format("%.1f ", ip.minData[component]); if (component == sequence.getSizeC() - 1) { char[] c = String.format("%.1f", xStart).toCharArray(); // x1 g.drawChars(c, 0, c.length, (int) rectBox.getMinX(), (int) rectBox.getMaxY() + 30); c = String.format("%.1f", xEnd).toCharArray(); // x2 g.drawChars(c, 0, c.length, (int) rectBox.getMaxX(), (int) rectBox.getMaxY() + 30); c = maxValue.toCharArray(); g.drawChars(c, 0, c.length, (int) rectBox.getMaxX() + 10, (int) rectBox.getMinY() + 10); c = minValue.toCharArray(); g.drawChars(c, 0, c.length, (int) rectBox.getMaxX() + 10, (int) rectBox.getMaxY() - 5); c = currentValueX.toCharArray(); g.drawChars( c, 0, c.length, (int) (rectBox.getMinX() + (ip.cursor1.x1 / ip.dataCount) * rectBox.getWidth()) - 20, (int) rectBox.getMaxY() + 15); c = currentValueV.toCharArray(); g.drawChars( c, 0, c.length, (int) (rectBox.getMinX() + (ip.cursor1.x1 / ip.dataCount) * rectBox.getWidth()) - 20, (int) rectBox.getMinY() - 5); } } } }
@Override public void paint(Graphics2D g, Sequence sequence, IcyCanvas canv) { if (canv != canvas) { canvas = canv; canvas.getViewer().addListener(this); canvas.getViewer().addKeyListener(this); } if (lastPoint == null) lastPoint = new Point(0, 0); // create a graphics object so that we can then dispose it at the end of the paint to clean // all change performed in the paint, // like transform, color change, stroke (...). HashMap<ROI2D, IntensityPaint> roiPairTemp = new HashMap<ROI2D, IntensityPaint>(); Graphics2D g2 = (Graphics2D) g.create(); for (ROI2D roi : sequence.getROI2Ds()) { if (roi.getName().startsWith("(") && roi.getName().endsWith(")")) continue; { IntensityPaint ip; if (roiPairDict.containsKey(roi)) { ip = roiPairDict.get(roi); // rect.displayRectangle.setName("["+roi.getName()+"]"); // Rectangle2D box2 = rect.displayRectangle.getBounds2D(); // // if(!sequence.getROI2Ds().contains(ip.displayRectangle)){// // sequence.removeROI(rect.displayRectangle);// // rect.displayRectangle.remove();// rect.displayRectangle new // ROI2DRectangle(lastPoint.getX(),lastPoint.getY(),Math.min(800,sequence.getWidth()),0);;;// rect.displayRectangle.setColor(roi.getColor());// sequence.addROI(rect.displayRectangle);// } if (ip != null) { if (!sequence.getROI2Ds().contains(ip.displayRectangle)) { ip.dispose(); } else roiPairTemp.put(roi, ip); } } else { ip = null; if (enableAddRoi) { roi.setName("" + Integer.toString(nameIndex) + "#"); nameIndex += 1; roi.setColor(getRandomColor()); // roi.setSelectedColor(getRandomColor()); ip = new IntensityPaint(roi, sequence, canvas); lastPoint.setLocation(lastPoint.getX() + 10, lastPoint.getY() + 10); if (lastPoint.getX() > sequence.getHeight() || lastPoint.getY() > sequence.getWidth()) lastPoint.setLocation(0, 0); sequence.addROI(ip.displayRectangle); } roiPairTemp.put(roi, ip); } if (ip != null && !skipSelect && roi instanceof ROI2DShape) { if (roi.isSelected()) ip.displayRectangle.setSelected(roi.isSelected()); else if (ip.displayRectangle.isSelected()) roi.setSelected(ip.displayRectangle.isSelected()); } try { if (ip != null) drawHisto(roi, g2, sequence, canvas); } catch (Exception e2) { } } } for (ROI2D roi : roiPairDict.keySet()) { if (!roiPairTemp.containsKey(roi)) { if (roiPairDict.get(roi) != null) { roiPairDict.get(roi).dispose(); sequence.removeROI(roiPairDict.get(roi).displayRectangle); } } } roiPairDict.clear(); roiPairDict = roiPairTemp; g2.dispose(); }
@Override public void sequenceClosed(Sequence sequence) { sequence.removeROI(displayRectangle); }
public void computeData() { computing = true; cancelCompute = false; try { maxData = new double[sequence.getSizeC()]; minData = new double[sequence.getSizeC()]; drawPolygon = new Polygon[sequence.getSizeC()]; if (paintMode == PaintMode.line) { Line2D line = ((ROI2DLine) guideRoi).getLine(); dataCount = (int) line.getP1().distance(line.getP2()); } else { dataCount = sequence.getSizeZ(); } dataArr = new ArrayList<double[]>(); for (int component = 0; component < sequence.getSizeC(); component++) { double[] data = new double[dataCount]; dataArr.add(data); } if (paintMode == PaintMode.line) { Line2D line = ((ROI2DLine) guideRoi).getLine(); dataCount = (int) line.getP1().distance(line.getP2()); ShapeUtil.consumeShapeFromPath( ((ROI2DShape) guideRoi).getPathIterator(null), new ShapeConsumer() { @Override public boolean consume(Shape shape) { if (shape instanceof Line2D) { Line2D line = (Line2D) shape; Point2D Lp; Point2D Rp; if (line.getX2() > line.getX1()) { Lp = line.getP1(); Rp = line.getP2(); } else { Lp = line.getP2(); Rp = line.getP1(); } for (int component = 0; component < sequence.getSizeC(); component++) { // create histo data int distance = dataCount; double vx = (Rp.getX() - Lp.getX()) / distance; double vy = (Rp.getY() - Lp.getY()) / distance; double[] data = dataArr.get(component); double x = Lp.getX(); double y = Lp.getY(); IcyBufferedImage image = canvas.getCurrentImage(); if (image.isInside((int) x, (int) y)) { maxData[component] = Array1DUtil.getValue( image.getDataXY(component), image.getOffset((int) x, (int) y), image.isSignedDataType()); } else { maxData[component] = 0; } minData[component] = maxData[component]; for (int i = 0; i < dataCount; i++) { if (cancelCompute) break; if (image.isInside((int) x, (int) y)) { data[i] = Array1DUtil.getValue( image.getDataXY(component), image.getOffset((int) x, (int) y), image.isSignedDataType()); } else { data[i] = 0; } if (data[i] > maxData[component]) maxData[component] = data[i]; if (data[i] < minData[component]) minData[component] = data[i]; x += vx; y += vy; } Polygon polygon = new Polygon(); polygon.addPoint(0, 0); for (int i = 0; i < dataCount; i++) { polygon.addPoint(i, (int) (data[i] - minData[component])); } polygon.addPoint(dataCount, 0); drawPolygon[component] = polygon; } } return true; // continue } }); } else { for (int component = 0; component < sequence.getSizeC(); component++) { double[] data = dataArr.get(component); if (paintMode == PaintMode.point) { Point p = guideRoi.getPosition(); if (p.x < sequence.getSizeX() && p.y < sequence.getSizeY()) { maxData[component] = sequence.getData(0, 0, component, p.y, p.x); minData[component] = maxData[component]; for (int i = 0; i < dataCount; i++) { if (cancelCompute) break; data[i] = sequence.getData(0, i, component, p.y, p.x); if (data[i] > maxData[component]) maxData[component] = data[i]; if (data[i] < minData[component]) minData[component] = data[i]; } } } else { maxData[component] = ROIUtil.getMeanIntensity(sequence, guideRoi, 0, -1, component); ; minData[component] = maxData[component]; for (int i = 0; i < dataCount; i++) { if (cancelCompute) break; data[i] = ROIUtil.getMeanIntensity(sequence, guideRoi, i, -1, component); if (data[i] > maxData[component]) maxData[component] = data[i]; if (data[i] < minData[component]) minData[component] = data[i]; } } Polygon polygon = new Polygon(); polygon.addPoint(0, 0); for (int i = 0; i < dataCount; i++) // pity polygon does not support this with double... polygon.addPoint(i, (int) (data[i] - minData[component])); polygon.addPoint(dataCount, 0); drawPolygon[component] = polygon; } } } catch (Exception e) { System.out.print(e); } computing = false; }
/** * Save the specified sequence in the specified file.<br> * When the sequence contains severals image the multipleFile flag is used to indicate<br> * if images are saved as separate files (file then specify a directory) or not.<br> * zMin - zMax and tMin - tMax define the Z and T images range to save.<br> * * @param formatWriter writer used to save sequence (define the image format) * @param sequence sequence to save * @param filePath file name where we want to save sequence * @param zMin start Z position to save * @param zMax end Z position to save * @param tMin start T position to save * @param tMax end T position to save * @param fps frame rate for AVI sequence save * @param saveFrame progress frame for save operation (can be null) * @throws ServiceException * @throws IOException * @throws FormatException */ private static void save( IFormatWriter formatWriter, Sequence sequence, String filePath, int zMin, int zMax, int tMin, int tMax, int fps, FileFrame saveFrame) throws ServiceException, FormatException, IOException { final File file = new File(filePath); final IFormatWriter writer; if (formatWriter == null) writer = getWriter(file, ImageFileFormat.TIFF); else writer = formatWriter; // TODO: temporary fix for the "incorrect close operation" bug in Bio-Formats // with OME TIF writer, remove it when fixed. // { // try // { // writer = formatWriter.getClass().newInstance(); // } // catch (Exception e) // { // throw new ServiceException("Can't create new writer instance: " + e); // } // } if (writer == null) throw new UnknownFormatException( "Can't find a valid image writer for the specified file: " + filePath); // first delete the file else LOCI won't save it correctly if (file.exists()) file.delete(); // ensure parent directory exist FileUtil.ensureParentDirExist(file); final int sizeC = sequence.getSizeC(); final boolean separateChannel = getSeparateChannelFlag(writer, sequence.getColorModel()); // set settings writer.setFramesPerSecond(fps); // generate metadata writer.setMetadataRetrieve( MetaDataUtil.generateMetaData( sequence, (zMax - zMin) + 1, (tMax - tMin) + 1, separateChannel)); // no interleave (XP default viewer want interleaved channel to correctly read image) writer.setInterleaved(false); // set id writer.setId(filePath); // init writer.setSeries(0); // usually give better save performance writer.setWriteSequentially(true); // get endianess final boolean littleEndian = !writer.getMetadataRetrieve().getPixelsBinDataBigEndian(0, 0).booleanValue(); byte[] data = null; try { int imageIndex = 0; // XYCZT order is important here (see metadata) for (int t = tMin; t <= tMax; t++) { for (int z = zMin; z <= zMax; z++) { if ((saveFrame != null) && saveFrame.isCancelRequested()) return; final IcyBufferedImage image = sequence.getImage(t, z); // separated channel data if (separateChannel) { for (int c = 0; c < sizeC; c++) { if (image != null) { // avoid multiple allocation data = image.getRawData(c, data, 0, littleEndian); writer.saveBytes(imageIndex, data); } imageIndex++; } } else { if (image != null) { // avoid multiple allocation data = image.getRawData(data, 0, littleEndian); writer.saveBytes(imageIndex, data); } imageIndex++; } if (saveFrame != null) saveFrame.incPosition(); } } } finally { // always close writer after a file has been saved writer.close(); } }
/** * Save the specified sequence in the specified file.<br> * When the sequence contains severals image the multipleFile flag is used to indicate if images * are saved as separate files (file then specify a directory) or not.<br> * <code>zMin</code> - <code>zMax</code> and <code>tMin</code> - <code>tMax</code> define the Z * and T images range to save.<br> * * @param formatWriter writer used to save sequence (define the image format).<br> * If set to <code>null</code> then writer is determined from the file extension.<br> * If destination file does not have a valid extension (for folder for instance) then you have * to specify a valid Writer to write the image file (see {@link #getWriter(ImageFileFormat)}) * @param sequence sequence to save * @param file file where we want to save sequence.<br> * Depending the <code>formatWriter</code> the file extension may be modified.<br> * That is preferred as saving an image with a wrong extension may result in error on future * read (wrong reader detection). * @param zMin start Z position to save * @param zMax end Z position to save * @param tMin start T position to save * @param tMax end T position to save * @param fps frame rate for AVI sequence save * @param multipleFile flag to indicate if images are saved in separate file * @param showProgress show progress bar * @param addToRecent add the saved sequence to recent opened sequence list */ public static void save( IFormatWriter formatWriter, Sequence sequence, File file, int zMin, int zMax, int tMin, int tMax, int fps, boolean multipleFile, boolean showProgress, boolean addToRecent) { final String filePath = FileUtil.cleanPath(FileUtil.getGenericPath(file.getAbsolutePath())); final int sizeT = (tMax - tMin) + 1; final int sizeZ = (zMax - zMin) + 1; final int numImages = sizeT * sizeZ; final FileFrame saveFrame; final ApplicationMenu mainMenu; if (addToRecent) mainMenu = Icy.getMainInterface().getApplicationMenu(); else mainMenu = null; if (showProgress && !Icy.getMainInterface().isHeadLess()) saveFrame = new FileFrame("Saving", filePath); else saveFrame = null; try { if (saveFrame != null) { saveFrame.setLength(numImages); saveFrame.setPosition(0); } // need multiple files ? if ((numImages > 1) && multipleFile) { final IFormatWriter writer; // so we won't create it for each image if (formatWriter == null) writer = getWriter(file, ImageFileFormat.TIFF); else writer = formatWriter; if (writer == null) throw new UnknownFormatException( "Can't find a valid image writer for the specified file: " + file); // save as severals images final DecimalFormat decimalFormat = new DecimalFormat("0000"); final String fileName = FileUtil.getFileName(filePath, false); String fileExt = FileUtil.getFileExtension(filePath, true); String fileBaseDirectory = FileUtil.getDirectory(filePath); if (fileBaseDirectory.endsWith("/")) fileBaseDirectory = fileBaseDirectory.substring(0, fileBaseDirectory.length() - 1); // no extension (directory) ? if (StringUtil.isEmpty(fileExt)) { // filename is part of directory fileBaseDirectory += FileUtil.separator + fileName; // use the default file extension for the specified writer fileExt = "." + getImageFileFormat(writer, ImageFileFormat.TIFF).getExtensions()[0]; } final String filePathWithoutExt = fileBaseDirectory + FileUtil.separator + fileName; // create output directory FileUtil.createDir(fileBaseDirectory); // default name used --> use filename if (sequence.isDefaultName()) sequence.setName(fileName); sequence.setFilename(fileBaseDirectory); for (int t = tMin; t <= tMax; t++) { for (int z = zMin; z <= zMax; z++) { String filename = filePathWithoutExt; if ((tMax - tMin) > 0) filename += "_t" + decimalFormat.format(t); if ((zMax - zMin) > 0) filename += "_z" + decimalFormat.format(z); filename += fileExt; // save as single image file save(writer, sequence, filename, z, z, t, t, fps, saveFrame); } } // add as one item to recent file list if (mainMenu != null) mainMenu.addRecentFile(fileBaseDirectory); } else { final String fileExt = FileUtil.getFileExtension(filePath, false); final ImageFileFormat iff; if (formatWriter != null) iff = getImageFileFormat(formatWriter, ImageFileFormat.TIFF); else iff = ImageFileFormat.getWriteFormat(fileExt, ImageFileFormat.TIFF); // force to set correct file extension final String fixedFilePath; if (iff.matches(fileExt)) fixedFilePath = filePath; else fixedFilePath = filePath + "." + iff.getExtensions()[0]; // default name used --> use filename if (sequence.isDefaultName()) sequence.setName(FileUtil.getFileName(fixedFilePath, false)); sequence.setFilename(fixedFilePath); // save into a single file save(formatWriter, sequence, fixedFilePath, zMin, zMax, tMin, tMax, fps, saveFrame); // add as one item to recent file list if (mainMenu != null) mainMenu.addRecentFile(fixedFilePath); } // Sequence persistence enabled --> save XML if (GeneralPreferences.getSequencePersistence()) sequence.saveXMLData(); } catch (Exception e) { IcyExceptionHandler.showErrorMessage(e, true); if (showProgress && !Icy.getMainInterface().isHeadLess()) new FailedAnnounceFrame("Failed to save image(s) (see output console for details)", 15); return; } finally { if (saveFrame != null) saveFrame.close(); } }
public void removeSequence(final Sequence sequence) { sequence.close(); }