File: ChannelSplitter.java

package info (click to toggle)
imagej 1.52j-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,604 kB
  • sloc: java: 120,017; sh: 279; xml: 161; makefile: 6
file content (152 lines) | stat: -rw-r--r-- 5,012 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package ij.plugin;
import ij.*;
import ij.process.*;
import ij.gui.*;
import ij.measure.Calibration;
import ij.plugin.HyperStackReducer;
import java.awt.*;
import java.util.Vector;

/** This plugin implements the Image/Color/Split Channels command. */
public class ChannelSplitter implements PlugIn {

	public void run(String arg) {
		ImagePlus imp = IJ.getImage();
		if (imp.isComposite()) {
			int z = imp.getSlice();
			int t = imp.getFrame();
			ImagePlus[] channels = split(imp);
			imp.changes = false;
			imp.setIgnoreFlush(true);
			imp.close();
			for (int i=0; i<channels.length; i++) {
				channels[i].setIJMenuBar(i==channels.length-1);
				channels[i].show();
				if (z>1 || t>1)
					channels[i].setPosition(1, z, t);
			}
		} else if (imp.getType()==ImagePlus.COLOR_RGB)
			splitRGB(imp);
		else 
			IJ.error("Split Channels", "Multichannel image required");
	}
	
	private void splitRGB(ImagePlus imp) {
		boolean keepSource = IJ.altKeyDown();
		String title = imp.getTitle();
		Calibration cal = imp.getCalibration();
		int pos = imp.getCurrentSlice();
		ImageStack[] channels = splitRGB(imp.getStack(), keepSource);
		if (!keepSource)
			{imp.unlock(); imp.changes=false; imp.close();}
		ImagePlus rImp = new ImagePlus(title+" (red)", channels[0]);
		rImp.setCalibration(cal);
		rImp.setIJMenuBar(false);
		rImp.show();
		rImp.setSlice(pos);
		if (IJ.isMacOSX()) IJ.wait(500);
		ImagePlus gImp = new ImagePlus(title+" (green)", channels[1]);
		gImp.setCalibration(cal);
		gImp.setIJMenuBar(false);
		gImp.show();
		gImp.setSlice(pos);
		if (IJ.isMacOSX()) IJ.wait(500);
		ImagePlus bImp = new ImagePlus(title+" (blue)", channels[2]);
		bImp.setCalibration(cal);
		bImp.show();
		bImp.setSlice(pos);
	}

	/** Splits the specified image into separate channels. */
	public static ImagePlus[] split(ImagePlus imp) {
		if (imp.getType()==ImagePlus.COLOR_RGB) {
			ImageStack[] stacks = splitRGB(imp.getStack(), true);
			ImagePlus[] images = new ImagePlus[3];
			images[0] = new ImagePlus("red", stacks[0]);
			images[1] = new ImagePlus("green", stacks[1]);
			images[2] = new ImagePlus("blue", stacks[2]);
			return images;
		}
		int width = imp.getWidth();
		int height = imp.getHeight();
		int channels = imp.getNChannels();
		int slices = imp.getNSlices();
		int frames = imp.getNFrames();
		int bitDepth = imp.getBitDepth();
		int size = slices*frames;
		Vector images = new Vector();
		HyperStackReducer reducer = new HyperStackReducer(imp);
		for (int c=1; c<=channels; c++) {
			ImageStack stack2 = new ImageStack(width, height, size); // create empty stack
			stack2.setPixels(imp.getProcessor().getPixels(), 1); // can't create ImagePlus will null 1st image
			ImagePlus imp2 = new ImagePlus("C"+c+"-"+imp.getTitle(), stack2);
			stack2.setPixels(null, 1);
			imp.setPosition(c, 1, 1);
			imp2.setDimensions(1, slices, frames);
			imp2.setCalibration(imp.getCalibration());
			reducer.reduce(imp2);
			if (imp.isComposite() && ((CompositeImage)imp).getMode()==IJ.GRAYSCALE)
				IJ.run(imp2, "Grays", "");
			if (imp2.getNDimensions()>3)
				imp2.setOpenAsHyperStack(true);
			images.add(imp2);
		}
		ImagePlus[] array = new ImagePlus[images.size()];
		return (ImagePlus[])images.toArray(array);
	}
	
	/** Returns, as an ImageStack, the specified channel, where 'c' must be greater 
		than zero and less than or equal to the number of channels in the image. */
	public static ImageStack getChannel(ImagePlus imp, int c) {
		if (imp.getBitDepth()==24) { // RGB?
			if (c<1 || c>3)
				throw new IllegalArgumentException("Channel must be 1,2 or 3");
			ImageStack[] channels = splitRGB(imp.getStack(), true);
			return channels[c-1];
		}
		if (c<1 || c>imp.getNChannels())
			throw new IllegalArgumentException("Channel less than 1 or greater than "+imp.getNChannels());
		ImageStack stack1 = imp.getStack();
		ImageStack stack2 = new ImageStack(imp.getWidth(), imp.getHeight());
		for (int t=1; t<=imp.getNFrames(); t++) {
			for (int z=1; z<=imp.getNSlices(); z++) {
				int n = imp.getStackIndex(c, z, t);
				stack2.addSlice(stack1.getProcessor(n));
			}
		}
		return stack2;
	}
	
	/** Splits the specified RGB stack into three 8-bit grayscale stacks. 
		Deletes the source stack if keepSource is false. */
	public static ImageStack[] splitRGB(ImageStack rgb, boolean keepSource) {
		 int w = rgb.getWidth();
		 int h = rgb.getHeight();
		 ImageStack[] channels = new ImageStack[3];
		 for (int i=0; i<3; i++)
		 	channels[i] = new ImageStack(w,h);
		 byte[] r,g,b;
		 ColorProcessor cp;
		 int slice = 1;
		 int inc = keepSource?1:0;
		 int n = rgb.getSize();
		 for (int i=1; i<=n; i++) {
			 IJ.showStatus(i+"/"+n);
			 r = new byte[w*h];
			 g = new byte[w*h];
			 b = new byte[w*h];
			 cp = (ColorProcessor)rgb.getProcessor(slice);
			 slice += inc;
			 cp.getRGB(r,g,b);
			 if (!keepSource)
				rgb.deleteSlice(1);
			 channels[0].addSlice(null,r);
			 channels[1].addSlice(null,g);
			 channels[2].addSlice(null,b);
			 IJ.showProgress((double)i/n);
		}
		return channels;
	}

}