package ij.plugin; import java.awt.*; import ij.*; import ij.process.*; import ij.gui.*; /** Converts a 2 or 3 slice stack, or a hyperstack, to RGB. */ public class RGBStackConverter implements PlugIn, DialogListener { private int channels1, slices1, frames1; private int slices2, frames2; private int width, height; private double imageSize; private static boolean staticKeep = true; private boolean keep; public void run(String arg) { ImagePlus imp = IJ.getImage(); if (!IJ.isMacro()) keep = staticKeep; CompositeImage cimg = imp.isComposite()?(CompositeImage)imp:null; int size = imp.getStackSize(); if ((size<2||size>3) && cimg==null) { IJ.error("A 2 or 3 image stack, or a HyperStack, required"); return; } int type = imp.getType(); if (cimg==null && !(type==ImagePlus.GRAY8 || type==ImagePlus.GRAY16)) { IJ.error("8-bit or 16-bit grayscale stack required"); return; } if (!imp.lock()) return; Undo.reset(); String title = imp.getTitle()+" (RGB)"; if (cimg!=null) compositeToRGB(cimg, title); else if (type==ImagePlus.GRAY16) { sixteenBitsToRGB(imp); } else { ImagePlus imp2 = imp.createImagePlus(); imp2.setStack(title, imp.getStack()); ImageConverter ic = new ImageConverter(imp2); ic.convertRGBStackToRGB(); imp2.show(); } imp.unlock(); } void compositeToRGB(CompositeImage imp, String title) { int channels = imp.getNChannels(); int slices = imp.getNSlices(); int frames = imp.getNFrames(); int images = channels*slices*frames; if (channels==images) { compositeImageToRGB(imp, title); return; } width = imp.getWidth(); height = imp.getHeight(); imageSize = width*height*4.0/(1024.0*1024.0); channels1 = imp.getNChannels(); slices1 = slices2 = imp.getNSlices(); frames1 = frames2 = imp.getNFrames(); int c1 = imp.getChannel(); int z1 = imp.getSlice(); int t2 = imp.getFrame(); if (!showDialog()) return; //IJ.log("HyperStackReducer-2: "+keep+" "+channels2+" "+slices2+" "+frames2); String title2 = keep?WindowManager.getUniqueName(imp.getTitle()):imp.getTitle(); ImagePlus imp2 = imp.createHyperStack(title2, 1, slices2, frames2, 24); convertHyperstack(imp, imp2); if (imp.getWindow()==null && !keep) { imp.setImage(imp2); return; } imp2.setOpenAsHyperStack(slices2>1||frames2>1); imp2.show(); if (!keep) { imp.changes = false; imp.close(); } } public void convertHyperstack(ImagePlus imp, ImagePlus imp2) { int slices = imp2.getNSlices(); int frames = imp2.getNFrames(); int c1 = imp.getChannel(); int z1 = imp.getSlice(); int t1 = imp.getFrame(); int i = 1; int c = 1; ImageStack stack = imp.getStack(); ImageStack stack2 = imp2.getStack(); imp.setPositionWithoutUpdate(c, 1, 1); ImageProcessor ip = imp.getProcessor(); double min = ip.getMin(); double max = ip.getMax(); for (int z=1; z<=slices; z++) { if (slices==1) z = z1; for (int t=1; t<=frames; t++) { //IJ.showProgress(i++, n); if (frames==1) t = t1; //ip = stack.getProcessor(n1); imp.setPositionWithoutUpdate(c, z, t); Image img = imp.getImage(); int n2 = imp2.getStackIndex(c, z, t); stack2.setPixels((new ColorProcessor(img)).getPixels(), n2); } } imp.setPosition(c1, z1, t1); imp2.resetStack(); imp2.setPosition(1, 1, 1); } void compositeImageToRGB(CompositeImage imp, String title) { if (imp.getMode()==CompositeImage.COMPOSITE) { ImagePlus imp2 = imp.createImagePlus(); imp.updateImage(); imp2.setProcessor(title, new ColorProcessor(imp.getImage())); imp2.show(); return; } ImageStack stack = new ImageStack(imp.getWidth(), imp.getHeight()); int c = imp.getChannel(); int n = imp.getNChannels(); for (int i=1; i<=n; i++) { imp.setPositionWithoutUpdate(i, 1, 1); stack.addSlice(null, new ColorProcessor(imp.getImage())); } imp.setPosition(c, 1, 1); ImagePlus imp2 = imp.createImagePlus(); imp2.setStack(title, stack); Object info = imp.getProperty("Info"); if (info!=null) imp2.setProperty("Info", info); imp2.show(); } void sixteenBitsToRGB(ImagePlus imp) { Roi roi = imp.getRoi(); int width, height; Rectangle r; if (roi!=null) { r = roi.getBounds(); width = r.width; height = r.height; } else r = new Rectangle(0,0,imp.getWidth(),imp.getHeight()); ImageProcessor ip; ImageStack stack1 = imp.getStack(); ImageStack stack2 = new ImageStack(r.width, r.height); for (int i=1; i<=stack1.getSize(); i++) { ip = stack1.getProcessor(i); ip.setRoi(r); ImageProcessor ip2 = ip.crop(); ip2 = ip2.convertToByte(true); stack2.addSlice(null, ip2); } ImagePlus imp2 = imp.createImagePlus(); imp2.setStack(imp.getTitle()+" (RGB)", stack2); ImageConverter ic = new ImageConverter(imp2); ic.convertRGBStackToRGB(); imp2.show(); } boolean showDialog() { GenericDialog gd = new GenericDialog("Convert to RGB"); gd.setInsets(10, 20, 5); gd.addMessage("Create RGB Image With:"); gd.setInsets(0, 35, 0); if (slices1!=1) gd.addCheckbox("Slices ("+slices1+")", true); gd.setInsets(0, 35, 0); if (frames1!=1) gd.addCheckbox("Frames ("+frames1+")", true); gd.setInsets(5, 20, 0); gd.addMessage(getNewDimensions()+" "); gd.setInsets(15, 20, 0); gd.addCheckbox("Keep Source", keep); gd.addDialogListener(this); gd.showDialog(); if (gd.wasCanceled()) return false; else return true; } public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { if (IJ.isMacOSX()) IJ.wait(100); if (slices1!=1) slices2 = gd.getNextBoolean()?slices1:1; if (frames1!=1) frames2 = gd.getNextBoolean()?frames1:1; keep = gd.getNextBoolean(); if (!IJ.isMacro()) staticKeep = keep; ((Label)gd.getMessage()).setText(getNewDimensions()); return true; } String getNewDimensions() { String s1 = slices2>1?"x"+slices2:""; String s2 = frames2>1?"x"+frames2:""; String s = width+"x"+height+s1+s2; s += " ("+(int)Math.round(imageSize*slices2*frames2)+"MB)"; return(s); } }