// // RecordedImageProcessor.java // /* LOCI Plugins for ImageJ: a collection of ImageJ plugins including the Bio-Formats Importer, Bio-Formats Exporter, Bio-Formats Macro Extensions, Data Browser and Stack Slicer. Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden and Christopher Peterson. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package loci.plugins.util; import ij.gui.ProgressBar; import ij.gui.Roi; import ij.process.ByteProcessor; import ij.process.FloatProcessor; import ij.process.ImageProcessor; import ij.process.ShortProcessor; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Image; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MemoryImageSource; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * Image processor extension that records commands executed upon it. * Allows "recordable virtual stacks" that repeat operations performed on * one image plane on other image planes when they are loaded from disk. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/loci-plugins/src/loci/plugins/util/RecordedImageProcessor.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/loci-plugins/src/loci/plugins/util/RecordedImageProcessor.java;hb=HEAD">Gitweb</a></dd></dl> * * @author Melissa Linkert melissa at glencoesoftware.com */ public class RecordedImageProcessor extends ImageProcessor { // -- Fields -- private ImageProcessor proc; private boolean doRecording; private List<MethodEntry> methodStack; private int channelNumber; private ImageProcessor[] otherChannels; // -- Constructor -- public RecordedImageProcessor(ImageProcessor proc) { this.proc = proc; methodStack = new ArrayList<MethodEntry>(); doRecording = true; } public RecordedImageProcessor(ImageProcessor proc, int channelNum, ImageProcessor[] otherChannels) { this.proc = proc; methodStack = new ArrayList<MethodEntry>(); doRecording = true; this.channelNumber = channelNum; this.otherChannels = otherChannels; } // -- RecordedImageProcessor API methods -- public void setDoRecording(boolean doRecording) { this.doRecording = doRecording; } public List<MethodEntry> getMethodStack() { return methodStack; } public void applyMethodStack(List<MethodEntry> stack) { for (int i=0; i<stack.size(); i++) { MethodEntry m = stack.get(i); try { m.method.invoke(proc, m.args); } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } } } public ImageProcessor getChild() { return proc; } // -- ImageProcessor API methods -- public void abs() { record("abs"); proc.abs(); } public void add(double value) { record("add", new Double(value), double.class); proc.add(value); } public void add(int value) { record("add", new Integer(value), int.class); proc.add(value); } public void and(int value) { record("and", new Integer(value), int.class); proc.and(value); } public void applyTable(int[] lut) { record("applyTable", lut, int[].class); proc.applyTable(lut); } public void autoThreshold() { record("autoThreshold"); proc.autoThreshold(); } public ImageProcessor convertToByte(boolean doScaling) { record("convertToByte", new Boolean(doScaling), boolean.class); return proc.convertToByte(doScaling); } public ImageProcessor convertToFloat() { record("convertToFloat"); return proc.convertToFloat(); } public ImageProcessor convertToRGB() { record("convertToRGB"); return proc.convertToRGB(); } public ImageProcessor convertToShort(boolean doScaling) { record("convertToShort", new Boolean(doScaling), boolean.class); return proc.convertToShort(doScaling); } public void convolve(float[] kernel, int kernelWidth, int kernelHeight) { record("convolve", new Object[] {kernel, new Integer(kernelWidth), new Integer(kernelHeight)}, new Class[] {float[].class, int.class, int.class}); proc.convolve(kernel, kernelWidth, kernelHeight); } public void convolve3x3(int[] kernel) { record("convolve3x3", kernel, int[].class); proc.convolve3x3(kernel); } public void copyBits(ImageProcessor ip, int xloc, int yloc, int mode) { record("copyBits", new Object[] {ip, new Integer(xloc), new Integer(yloc), new Integer(mode)}, new Class[] {ImageProcessor.class, int.class, int.class, int.class}); proc.copyBits(ip, xloc, yloc, mode); } public Image createImage() { if (otherChannels == null) return proc.createImage(); // merge channels - adapted from CompositeImage int size = proc.getWidth() * proc.getHeight(); int[] rgbPixels = new int[size]; for (int i=0; i<otherChannels.length+1; i++) { ImageProcessor activeProcessor = null; if (i == channelNumber) { activeProcessor = proc; } else { if (i < channelNumber) activeProcessor = otherChannels[i]; else activeProcessor = otherChannels[i - 1]; } IndexColorModel cm = (IndexColorModel) activeProcessor.getColorModel(); int mapSize = cm.getMapSize(); int[] reds = new int[mapSize]; int[] greens = new int[mapSize]; int[] blues = new int[mapSize]; byte[] tmp = new byte[mapSize]; cm.getReds(tmp); for (int q=0; q<mapSize; q++) { reds[q] = (tmp[q] & 0xff) << 16; } cm.getGreens(tmp); for (int q=0; q<mapSize; q++) { greens[q] = (tmp[q] & 0xff) << 8; } cm.getBlues(tmp); for (int q=0; q<mapSize; q++) { blues[q] = tmp[q] & 0xff; } byte[] pixels = new byte[size]; double min = activeProcessor.getMin(); double max = activeProcessor.getMax(); double scale = 256.0 / (max - min + 1); if (activeProcessor instanceof ByteProcessor) { pixels = (byte[]) activeProcessor.getPixels(); } else if (activeProcessor instanceof ShortProcessor) { short[] s = (short[]) activeProcessor.getPixels(); for (int q=0; q<size; q++) { int value = (int) ((s[q] & 0xffff) - min); if (value < 0) value = 0; value = (int) (value * scale + 0.5); if (value > 255) value = 255; pixels[q] = (byte) value; } } else if (activeProcessor instanceof FloatProcessor) { float[] f = (float[]) activeProcessor.getPixels(); for (int q=0; q<size; q++) { float value = (float) (f[q] - min); if (value < 0) value = 0f; int ivalue = (int) (value * scale); if (ivalue > 255) ivalue = 255; pixels[q] = (byte) ivalue; } } switch (i) { case 0: for (int q=0; q<size; q++) { rgbPixels[q] = (rgbPixels[q] & 0xff00ffff) | reds[pixels[q] & 0xff]; } break; case 1: for (int q=0; q<size; q++) { rgbPixels[q] = (rgbPixels[q] & 0xffff00ff) | greens[pixels[q] & 0xff]; } break; case 2: for (int q=0; q<size; q++) { rgbPixels[q] = (rgbPixels[q] & 0xffffff00) | blues[pixels[q] & 0xff]; } break; case 3: for (int q=0; q<size; q++) { int red = reds[pixels[q] & 0xff]; int green = greens[pixels[q] & 0xff]; int blue = blues[pixels[q] & 0xff]; rgbPixels[q] = red | green | blue; } break; default: for (int q=0; q<size; q++) { int pixel = rgbPixels[q]; int red = (pixel & 0xff0000) + reds[pixels[q] & 0xff]; int green = (pixel & 0x00ff00) + greens[pixels[q] & 0xff]; int blue = (pixel & 0xff) + blues[pixels[q] & 0xff]; if (red > 16711680) red = 16711680; if (green > 65280) green = 65280; if (blue > 255) blue = 255; rgbPixels[q] = red | green | blue; } } } DirectColorModel rgb = new DirectColorModel(32, 0xff0000, 0xff00, 0xff); MemoryImageSource src = new MemoryImageSource(proc.getWidth(), proc.getHeight(), rgb, rgbPixels, 0, proc.getWidth()); src.setAnimated(true); src.setFullBufferUpdates(true); return Toolkit.getDefaultToolkit().createImage(src); } public ImageProcessor createProcessor(int width, int height) { record("createProcessor", new Object[] {new Integer(width), new Integer(height)}, new Class[] {int.class, int.class}); return proc.createProcessor(width, height); } public ImageProcessor crop() { record("crop"); return proc.crop(); } public void dilate() { record("dilate"); proc.dilate(); } public void drawDot(int xcenter, int ycenter) { record("drawDot", new Object[] {new Integer(xcenter), new Integer(ycenter)}, new Class[] {int.class, int.class}); proc.drawDot(xcenter, ycenter); } public void drawLine(int x1, int y1, int x2, int y2) { record("drawLine", new Object[] {new Integer(x1), new Integer(y1), new Integer(x2), new Integer(y2)}, new Class[] {int.class, int.class, int.class, int.class}); proc.drawLine(x1, y1, x2, y2); } public void drawOval(int x, int y, int width, int height) { record("drawOval", new Object[] {new Integer(x), new Integer(y), new Integer(width), new Integer(height)}, new Class[] {int.class, int.class, int.class, int.class}); proc.drawOval(x, y, width, height); } public void drawPixel(int x, int y) { record("drawPixel", new Object[] {new Integer(x), new Integer(y)}, new Class[] {int.class, int.class}); proc.drawPixel(x, y); } public void drawPolygon(Polygon p) { record("drawPolygon", p, Polygon.class); proc.drawPolygon(p); } public void drawRect(int x, int y, int width, int height) { record("drawRect", new Object[] {new Integer(x), new Integer(y), new Integer(width), new Integer(height)}, new Class[] {int.class, int.class, int.class, int.class}); proc.drawRect(x, y, width, height); } public void drawString(String s) { record("drawString", s, String.class); proc.drawString(s); } public void drawString(String s, int x, int y) { record("drawString", new Object[] {s, new Integer(x), new Integer(y)}, new Class[] {String.class, int.class, int.class}); proc.drawString(s, x, y); } public ImageProcessor duplicate() { record("duplicate"); return proc.duplicate(); } public void erode() { record("erode"); proc.erode(); } public void exp() { record("exp"); proc.exp(); } public void fill() { record("fill"); proc.fill(); } public void fill(ImageProcessor mask) { record("fill", mask, ImageProcessor.class); proc.fill(mask); } public void fillOval(int x, int y, int width, int height) { record("fillOval", new Object[] {new Integer(x), new Integer(y), new Integer(width), new Integer(height)}, new Class[] {int.class, int.class, int.class, int.class}); proc.fillOval(x, y, width, height); } public void fillPolygon(Polygon p) { record("fillPolygon", p, Polygon.class); proc.fillPolygon(p); } public void filter(int type) { record("filter", new Integer(type), int.class); proc.filter(type); } public void findEdges() { record("findEdges"); proc.findEdges(); } public void flipHorizontal() { record("flipHorizontal"); proc.flipHorizontal(); } public void flipVertical() { record("flipVertical"); proc.flipVertical(); } public void gamma(double value) { record("gamma", new Double(value), double.class); proc.gamma(value); } public int get(int index) { record("get", new Integer(index), int.class); return proc.get(index); } public int get(int x, int y) { record("get", new Object[] {new Integer(x), new Integer(y)}, new Class[] {int.class, int.class}); return proc.get(x, y); } public int getAutoThreshold() { record("getAutoThreshold"); return proc.getAutoThreshold(); } public double getBackgroundValue() { record("getBackgroundValue"); return proc.getBackgroundValue(); } public int getAutoThreshold(int[] histogram) { record("getAutoThreshold", histogram, int[].class); return proc.getAutoThreshold(histogram); } public int getBestIndex(Color c) { record("getBestIndex", c, Color.class); return proc.getBestIndex(c); } public BufferedImage getBufferedImage() { record("getBufferedImage"); return proc.getBufferedImage(); } public float[] getCalibrationTable() { record("getCalibrationTable"); return proc.getCalibrationTable(); } public ColorModel getColorModel() { record("getColorModel"); return proc.getColorModel(); } public void getColumn(int x, int y, int[] data, int length) { record("getColumn", new Object[] {new Integer(x), new Integer(y), data, new Integer(length)}, new Class[] {int.class, int.class, int[].class, int.class}); proc.getColumn(x, y, data, length); } public ColorModel getCurrentColorModel() { record("getCurrentColorModel"); return proc.getCurrentColorModel(); } public IndexColorModel getDefaultColorModel() { record("getDefaultColorModel"); return proc.getDefaultColorModel(); } public float getf(int index) { record("getf", new Integer(index), int.class); return proc.getf(index); } public float getf(int x, int y) { record("getf", new Object[] {new Integer(x), new Integer(y)}, new Class[] {int.class, int.class}); return proc.getf(x, y); } public float[][] getFloatArray() { record("getFloatArray"); return proc.getFloatArray(); } public FontMetrics getFontMetrics() { record("getFontMetrics"); return proc.getFontMetrics(); } public int getHeight() { record("getHeight"); return proc.getHeight(); } public int[] getHistogram() { record("getHistogram"); return proc.getHistogram(); } public double getHistogramMax() { record("getHistogramMax"); return proc.getHistogramMax(); } public double getHistogramMin() { record("getHistogramMin"); return proc.getHistogramMin(); } public int getHistogramSize() { record("getHistogramSize"); return proc.getHistogramSize(); } public int[][] getIntArray() { record("getIntArray"); return proc.getIntArray(); } public boolean getInterpolate() { record("getInterpolate"); return proc.getInterpolate(); } public double getInterpolatedPixel(double x, double y) { record("getInterpolatedPixel", new Object[] {new Double(x), new Double(y)}, new Class[] {double.class, double.class}); return proc.getInterpolatedPixel(x, y); } public double[] getLine(double x1, double y1, double x2, double y2) { record("getLine", new Object[] {new Double(x1), new Double(y1), new Double(x2), new Double(y2)}, new Class[] {double.class, double.class, double.class, double.class}); return proc.getLine(x1, y1, x2, y2); } public int getLutUpdateMode() { record("getLutUpdateMode"); return proc.getLutUpdateMode(); } public ImageProcessor getMask() { record("getMask"); return proc.getMask(); } public byte[] getMaskArray() { record("getMaskArray"); return proc.getMaskArray(); } public double getMax() { record("getMax"); return proc.getMax(); } public double getMaxThreshold() { record("getMaxThreshold"); return proc.getMaxThreshold(); } public double getMin() { record("getMin"); return proc.getMin(); } public double getMinThreshold() { record("getMinThreshold"); return proc.getMinThreshold(); } public int getNChannels() { record("getNChannels"); return proc.getNChannels(); } public int getPixel(int x, int y) { record("getPixel", new Object[] {new Integer(x), new Integer(y)}, new Class[] {int.class, int.class}); return proc.getPixel(x, y); } public int[] getPixel(int x, int y, int[] iArray) { record("getPixel", new Object[] {new Integer(x), new Integer(y), iArray}, new Class[] {int.class, int.class, int[].class}); return proc.getPixel(x, y, iArray); } public int getPixelInterpolated(double x, double y) { record("getPixelInterpolated", new Object[] {new Double(x), new Double(y)}, new Class[] {double.class, double.class}); return proc.getPixelInterpolated(x, y); } public int getPixelCount() { record("getPixelCount"); return proc.getPixelCount(); } public Object getPixels() { record("getPixels"); return proc.getPixels(); } public Object getPixelsCopy() { record("getPixelsCopy"); return proc.getPixelsCopy(); } public float getPixelValue(int x, int y) { record("getPixelValue", new Object[] {new Integer(x), new Integer(y)}, new Class[] {int.class, int.class}); return proc.getPixelValue(x, y); } public Rectangle getRoi() { record("getRoi"); return proc.getRoi(); } public void getRow(int x, int y, int[] data, int length) { record("getRow", new Object[] {new Integer(x), new Integer(y), data, new Integer(length)}, new Class[] {int.class, int.class, int[].class, int.class}); proc.getRow(x, y, data, length); } public Object getSnapshotPixels() { record("getSnapshotPixels"); return proc.getSnapshotPixels(); } public int getStringWidth(String s) { record("getStringWidth", s, String.class); return proc.getStringWidth(s); } public int getWidth() { record("getWidth"); return proc.getWidth(); } public void insert(ImageProcessor ip, int xloc, int yloc) { record("insert", new Object[] {ip, new Integer(xloc), new Integer(yloc)}, new Class[] {ImageProcessor.class, int.class, int.class}); proc.insert(ip, xloc, yloc); } public void invert() { record("invert"); proc.invert(); } public void invertLut() { record("invertLut"); proc.invertLut(); } public boolean isColorLut() { record("isColorLut"); return proc.isColorLut(); } public boolean isInvertedLut() { record("isInvertedLut"); return proc.isInvertedLut(); } public boolean isPseudoColorLut() { record("isPseudoColorLut"); return proc.isPseudoColorLut(); } public void lineTo(int x2, int y2) { record("lineTo", new Object[] {new Integer(x2), new Integer(y2)}, new Class[] {int.class, int.class}); proc.lineTo(x2, y2); } public void log() { record("log"); proc.log(); } public void max(double value) { record("max", new Double(value), double.class); proc.max(value); } public double maxValue() { record("maxValue"); return proc.maxValue(); } public void medianFilter() { record("medianFilter"); proc.medianFilter(); } public void min(double value) { record("min", new Double(value), double.class); proc.min(value); } public double minValue() { record("minValue"); return proc.minValue(); } public void moveTo(int x, int y) { record("moveTo", new Object[] {new Integer(x), new Integer(y)}, new Class[] {int.class, int.class}); proc.moveTo(x, y); } public void multiply(double value) { record("multiply", new Double(value), double.class); proc.multiply(value); } public void noise(double range) { record("noise", new Double(range), double.class); proc.noise(range); } public void or(int value) { record("or", new Integer(value), int.class); proc.or(value); } public void putColumn(int x, int y, int[] data, int length) { record("putColumn", new Object[] {new Integer(x), new Integer(y), data, new Integer(length)}, new Class[] {int.class, int.class, int[].class, int.class}); proc.putColumn(x, y, data, length); } public void putPixel(int x, int y, int value) { record("putPixel", new Object[] {new Integer(x), new Integer(y), new Integer(value)}, new Class[] {int.class, int.class, int.class}); proc.putPixel(x, y, value); } public void putPixel(int x, int y, int[] iArray) { record("putPixel", new Object[] {new Integer(x), new Integer(y), iArray}, new Class[] {int.class, int.class, int[].class}); proc.putPixel(x, y, iArray); } public void putPixelValue(int x, int y, double value) { record("putPixelValue", new Object[] {new Integer(x), new Integer(y), new Double(value)}, new Class[] {int.class, int.class, double.class}); proc.putPixelValue(x, y, value); } public void putRow(int x, int y, int[] data, int length) { record("putRow", new Object[] {new Integer(x), new Integer(y), data, new Integer(length)}, new Class[] {int.class, int.class, int[].class, int.class}); proc.putRow(x, y, data, length); } public void reset() { record("reset"); proc.reset(); } public void reset(ImageProcessor mask) { record("reset", mask, ImageProcessor.class); proc.reset(mask); } public void resetBinaryThreshold() { record("resetBinaryThreshold"); proc.resetBinaryThreshold(); } public void resetMinAndMax() { record("resetMinAndMax"); proc.resetMinAndMax(); } public void resetRoi() { record("resetRoi"); proc.resetRoi(); } public void resetThreshold() { record("resetThreshold"); proc.resetThreshold(); } public ImageProcessor resize(int dstWidth) { record("resize", new Integer(dstWidth), int.class); return proc.resize(dstWidth); } public ImageProcessor resize(int dstWidth, int dstHeight) { record("resize", new Object[] {new Integer(dstWidth), new Integer(dstHeight)}, new Class[] {int.class, int.class}); return proc.resize(dstWidth, dstHeight); } public void rotate(double angle) { record("rotate", new Double(angle), double.class); proc.rotate(angle); } public ImageProcessor rotateLeft() { record("rotateLeft"); return proc.rotateLeft(); } public ImageProcessor rotateRight() { record("rotateRight"); return proc.rotateRight(); } public void scale(double xScale, double yScale) { record("scale", new Object[] {new Double(xScale), new Double(yScale)}, new Class[] {double.class, double.class}); proc.scale(xScale, yScale); } public void set(int index, int value) { record("set", new Object[] {new Integer(index), new Integer(value)}, new Class[] {int.class, int.class}); proc.set(index, value); } public void set(int x, int y, int value) { record("set", new Object[] {new Integer(x), new Integer(y), new Integer(value)}, new Class[] {int.class, int.class, int.class}); proc.set(x, y, value); } public void setAntialiasedText(boolean antialiased) { record("setAntialiasedText", new Boolean(antialiased), boolean.class); proc.setAntialiasedText(antialiased); } public void setAutoThreshold(int method, int lutUpdate) { record("setAutoThreshold", new Object[] {new Integer(method), new Integer(lutUpdate)}, new Class[] {int.class, int.class}); proc.setAutoThreshold(method, lutUpdate); } public void setBackgroundValue(double value) { record("setBackgroundValue", new Double(value), double.class); proc.setBackgroundValue(value); } public void setCalibrationTable(float[] ctable) { record("setCalibrationTable", ctable, float[].class); proc.setCalibrationTable(ctable); } public void setClipRect(Rectangle clipRect) { record("setClipRect", clipRect, Rectangle.class); proc.setClipRect(clipRect); } public void setColor(Color color) { record("setColor", color, Color.class); proc.setColor(color); } public void setColor(int value) { record("setColor", new Integer(value), int.class); proc.setColor(value); } public void setColorModel(ColorModel cm) { record("setColorModel", cm, ColorModel.class); proc.setColorModel(cm); } public void setf(int index, float value) { record("setf", new Object[] {new Integer(index), new Float(value)}, new Class[] {int.class, float.class}); proc.setf(index, value); } public void setf(int x, int y, float value) { record("setf", new Object[] {new Integer(x), new Integer(y), new Float(value)}, new Class[] {int.class, int.class, float.class}); proc.setf(x, y, value); } public void setFloatArray(float[][] a) { record("setFloatArray", a, float[][].class); proc.setFloatArray(a); } public void setFont(Font font) { record("setFont", font, Font.class); proc.setFont(font); } public void setHistogramRange(double histMin, double histMax) { record("setHistogramRange", new Object[] {new Double(histMin), new Double(histMax)}, new Class[] {double.class, double.class}); proc.setHistogramRange(histMin, histMax); } public void setHistogramSize(int size) { record("setHistogramSize", new Integer(size), int.class); proc.setHistogramSize(size); } public void setIntArray(int[][] a) { record("setIntArray", a, int[][].class); proc.setIntArray(a); } public void setInterpolate(boolean interpolate) { record("setInterpolate", new Boolean(interpolate), boolean.class); proc.setInterpolate(interpolate); } public void setJustification(int justification) { record("setJustification", new Integer(justification), int.class); proc.setJustification(justification); } public void setLineWidth(int width) { record("setLineWidth", new Integer(width), int.class); proc.setLineWidth(width); } public void setLutAnimation(boolean lutAnimation) { record("setLutAnimation", new Boolean(lutAnimation), boolean.class); proc.setLutAnimation(lutAnimation); } public void setMask(ImageProcessor mask) { record("setMask", mask, ImageProcessor.class); proc.setMask(mask); } public void setMinAndMax(double min, double max) { record("setMinAndMax", new Object[] {new Double(min), new Double(max)}, new Class[] {double.class, double.class}); proc.setMinAndMax(min, max); } public void setPixels(int channelNumber, FloatProcessor fp) { record("setPixels", new Object[] {new Integer(channelNumber), fp}, new Class[] {int.class, FloatProcessor.class}); proc.setPixels(channelNumber, fp); } public void setPixels(Object pixels) { record("setPixels", pixels, Object.class); proc.setPixels(pixels); } public void setProgressBar(ProgressBar pb) { record("setProgressBar", pb, ProgressBar.class); proc.setProgressBar(pb); } public void setRoi(int x, int y, int rwidth, int rheight) { record("setRoi", new Object[] {new Integer(x), new Integer(y), new Integer(rwidth), new Integer(rheight)}, new Class[] {int.class, int.class, int.class, int.class}); proc.setRoi(x, y, rwidth, rheight); } public void setRoi(Polygon roi) { record("setRoi", roi, Polygon.class); proc.setRoi(roi); } public void setRoi(Rectangle roi) { record("setRoi", roi, Rectangle.class); proc.setRoi(roi); } public void setRoi(Roi roi) { record("setRoi", roi, Roi.class); proc.setRoi(roi); } public void setSnapshotCopyMode(boolean b) { record("setSnapshotCopyMode", new Boolean(b), boolean.class); proc.setSnapshotCopyMode(b); } public void setSnapshotPixels(Object pixels) { record("setSnapshotPixels", pixels, Object.class); proc.setSnapshotPixels(pixels); } public void setThreshold(double minThreshold, double maxThreshold, int lutUpdate) { record("setThreshold", new Object[] {new Double(minThreshold), new Double(maxThreshold), new Integer(lutUpdate)}, new Class[] {double.class, double.class, int.class}); proc.setThreshold(minThreshold, maxThreshold, lutUpdate); } public void setValue(double value) { record("setValue", new Double(value), double.class); proc.setValue(value); } public void sharpen() { record("sharpen"); proc.sharpen(); } public void smooth() { record("smooth"); proc.smooth(); } public void snapshot() { record("snapshot"); proc.snapshot(); } public void sqr() { record("sqr"); proc.sqr(); } public void sqrt() { record("sqrt"); proc.sqrt(); } public void swapPixelArrays() { record("swapPixelArrays"); proc.swapPixelArrays(); } public void threshold(int level) { record("threshold", new Integer(level), int.class); proc.threshold(level); } public FloatProcessor toFloat(int channelNumber, FloatProcessor fp) { record("toFloat", new Object[] {new Integer(channelNumber), fp}, new Class[] {int.class, FloatProcessor.class}); return proc.toFloat(channelNumber, fp); } public String toString() { record("toString"); return proc.toString(); } public void translate(int xOffset, int yOffset) { record("translate", new Object[] {new Integer(xOffset), new Integer(yOffset)}, new Class[] {int.class, int.class}); proc.translate(xOffset, yOffset); } public void updateComposite(int[] rgbPixels, int channel) { record("updateComposite", new Object[] {rgbPixels, new Integer(channel)}, new Class[] {int[].class, int.class}); proc.updateComposite(rgbPixels, channel); } public void xor(int value) { record("xor", new Integer(value), int.class); proc.xor(value); } // -- Deprecated methods -- /** @deprecated */ public void drawDot2(int x, int y) { record("drawDot2", new Object[] {new Integer(x), new Integer(y)}, new Class[] {int.class, int.class}); proc.drawDot2(x, y); } /** @deprecated */ public boolean isKillable() { record("isKillable"); return proc.isKillable(); } // -- Helper methods -- private void record(String method) { record(method, (Object[]) null, (Class<?>) null); } private void record(String method, Object v, Class<?> c) { record(method, v == null ? null : new Object[] {v}, c == null ? null : new Class<?>[] {c}); } private void record(String method, Object[] v, Class<?>[] c) { if (!doRecording) return; MethodEntry m = new MethodEntry(); m.name = method; m.args = v; if (v == null && c != null) { m.args = new Object[c.length]; for (int i=0; i<m.args.length; i++) { m.args[i] = null; } } try { m.method = proc.getClass().getMethod(method, c); } catch (NoSuchMethodException e) { } methodStack.add(m); } // -- Helper class -- class MethodEntry { public String name; public Object[] args; public Method method; } }