| ImageConverter |

    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();
            ip.setCalibrationTable(cal.getCTable());
            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);
        }

        /** 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());
            int width = imp.getWidth();
            int height = imp.getHeight();
            byte[] H = new byte[width*height];
            byte[] S = new byte[width*height];
            byte[] B = new byte[width*height];
            cp.getHSB(H, S, B);
            imp.trimProcessor();

            //create stack and select hue channel
            ColorModel cm = LookUpTable.createGrayscaleColorModel(false);
            ImageStack stack = new ImageStack(width, height, cm);
            stack.addSlice("Hue", H);
            stack.addSlice("Saturation", S);
            stack.addSlice("Brightness", B);
            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;
        }
    }

| ImageConverter |