package ij.process; import java.awt.*; import java.awt.image.*; import ij.*; import ij.gui.*; import ij.measure.*; /** This class converts an ImagePlus object to a different type. */ public class ImageConverter { private ImagePlus imp; private int type; //private static boolean doScaling = Prefs.getBoolean(Prefs.SCALE_CONVERSIONS,true); private static boolean doScaling = true; /** Constructs an ImageConverter based on an ImagePlus object. */ public ImageConverter(ImagePlus imp) { this.imp = imp; type = imp.getType(); } /** Converts this ImagePlus to 8-bit grayscale. */ public synchronized void convertToGray8() { if (imp.getStackSize()>1) throw new IllegalArgumentException("Unsupported conversion"); ImageProcessor ip = imp.getProcessor(); if (type==ImagePlus.GRAY16 || type==ImagePlus.GRAY32) { imp.setProcessor(null, ip.convertToByte(doScaling)); imp.setCalibration(imp.getCalibration()); //update calibration } else if (type==ImagePlus.COLOR_RGB) imp.setProcessor(null, ip.convertToByte(doScaling)); else if (ip.isPseudoColorLut()) { boolean invertedLut = ip.isInvertedLut(); ip.setColorModel(LookUpTable.createGrayscaleColorModel(invertedLut)); imp.updateAndDraw(); } else { ip = new ColorProcessor(imp.getImage()); imp.setProcessor(null, ip.convertToByte(doScaling)); } ImageProcessor ip2 = imp.getProcessor(); if (Prefs.useInvertingLut && ip2 instanceof ByteProcessor && !ip2.isInvertedLut()&& !ip2.isColorLut()) { ip2.invertLut(); ip2.invert(); } } /** Converts this ImagePlus to 16-bit grayscale. */ public void convertToGray16() { if (type==ImagePlus.GRAY16) return; if (!(type==ImagePlus.GRAY8||type==ImagePlus.GRAY32||type==ImagePlus.COLOR_RGB)) throw new IllegalArgumentException("Unsupported conversion"); ImageProcessor ip = imp.getProcessor(); imp.trimProcessor(); imp.setProcessor(null, ip.convertToShort(doScaling)); imp.setCalibration(imp.getCalibration()); //update calibration } /** Converts this ImagePlus to 32-bit grayscale. */ public void convertToGray32() { if (type==ImagePlus.GRAY32) return; if (!(type==ImagePlus.GRAY8||type==ImagePlus.GRAY16||type==ImagePlus.COLOR_RGB)) throw new IllegalArgumentException("Unsupported conversion"); ImageProcessor ip = imp.getProcessor(); imp.trimProcessor(); Calibration cal = imp.getCalibration(); imp.setProcessor(null, ip.convertToFloat()); imp.setCalibration(cal); //update calibration } /** Converts this ImagePlus to RGB. */ public void convertToRGB() { ImageProcessor ip = imp.getProcessor(); imp.setProcessor(null, ip.convertToRGB()); imp.setCalibration(imp.getCalibration()); //update calibration } /** Converts an RGB image to an RGB (red, green and blue) stack. */ public void convertToRGBStack() { if (type!=ImagePlus.COLOR_RGB) throw new IllegalArgumentException("Image must be RGB"); //convert to RGB Stack ColorProcessor cp; if (imp.getType()==ImagePlus.COLOR_RGB) cp = (ColorProcessor)imp.getProcessor(); else cp = new ColorProcessor(imp.getImage()); int width = imp.getWidth(); int height = imp.getHeight(); byte[] R = new byte[width*height]; byte[] G = new byte[width*height]; byte[] B = new byte[width*height]; cp.getRGB(R, G, B); imp.trimProcessor(); // Create stack and select Red channel ColorModel cm = LookUpTable.createGrayscaleColorModel(false); ImageStack stack = new ImageStack(width, height, cm); stack.addSlice("Red", R); stack.addSlice("Green", G); stack.addSlice("Blue", B); imp.setStack(null, stack); imp.setDimensions(3, 1, 1); if (imp.isComposite()) ((CompositeImage)imp).setMode(CompositeImage.GRAYSCALE); } /** Converts an RGB image to a HSB (hue, saturation and brightness) stack. */ public void convertToHSB() { if (type!=ImagePlus.COLOR_RGB) throw new IllegalArgumentException("Image must be RGB"); //convert to hue, saturation and brightness //IJ.showProgress(0.1); ColorProcessor cp; if (imp.getType()==ImagePlus.COLOR_RGB) cp = (ColorProcessor)imp.getProcessor(); else cp = new ColorProcessor(imp.getImage()); ImageStack stack = cp.getHSBStack(); imp.trimProcessor(); imp.setStack(null, stack); imp.setDimensions(3, 1, 1); //IJ.showProgress(1.0); } /** Converts a 2 or 3 slice 8-bit stack to RGB. */ public void convertRGBStackToRGB() { int stackSize = imp.getStackSize(); if (stackSize<2 || stackSize>3 || type!=ImagePlus.GRAY8) throw new IllegalArgumentException("2 or 3 slice 8-bit stack required"); int width = imp.getWidth(); int height = imp.getHeight(); ImageStack stack = imp.getStack(); byte[] R = (byte[])stack.getPixels(1); byte[] G = (byte[])stack.getPixels(2); byte[] B; if (stackSize>2) B = (byte[])stack.getPixels(3); else B = new byte[width*height]; imp.trimProcessor(); ColorProcessor cp = new ColorProcessor(width, height); cp.setRGB(R, G, B); if (imp.isInvertedLut()) cp.invert(); imp.setImage(cp.createImage()); imp.killStack(); } /** Converts a 3-slice (hue, saturation, brightness) 8-bit stack to RGB. */ public void convertHSBToRGB() { if (imp.getStackSize()!=3) throw new IllegalArgumentException("3-slice 8-bit stack required"); ImageStack stack = imp.getStack(); byte[] H = (byte[])stack.getPixels(1); byte[] S = (byte[])stack.getPixels(2); byte[] B = (byte[])stack.getPixels(3); int width = imp.getWidth(); int height = imp.getHeight(); imp.trimProcessor(); ColorProcessor cp = new ColorProcessor(width, height); cp.setHSB(H, S, B); imp.setImage(cp.createImage()); imp.killStack(); } /** Converts an RGB image to 8-bits indexed color. 'nColors' must be greater than 1 and less than or equal to 256. */ public void convertRGBtoIndexedColor(int nColors) { if (type!=ImagePlus.COLOR_RGB) throw new IllegalArgumentException("Image must be RGB"); if (nColors<2) nColors = 2; if (nColors>256) nColors = 256; // get RGB pixels IJ.showProgress(0.1); IJ.showStatus("Grabbing pixels"); int width = imp.getWidth(); int height = imp.getHeight(); ImageProcessor ip = imp.getProcessor(); ip.snapshot(); int[] pixels = (int[])ip.getPixels(); imp.trimProcessor(); // convert to 8-bits long start = System.currentTimeMillis(); MedianCut mc = new MedianCut(pixels, width, height); ImageProcessor ip2 = mc.convertToByte(nColors); imp.setProcessor(null, ip2); } /** Set true to scale to 0-255 when converting short to byte or float to byte and to 0-65535 when converting float to short. */ public static void setDoScaling(boolean scaleConversions) { doScaling = scaleConversions; IJ.register(ImageConverter.class); } /** Returns true if scaling is enabled. */ public static boolean getDoScaling() { return doScaling; } }