7 import java.awt.image.*;
10 import java.util.Vector;
11 import java.awt.event.*;
16 Button openButton, saveButton, resizeButton, invertButton;
17 ColorPanel colorPanel;
19 public void run(String args) {
29 colorPanel =
new ColorPanel(imp);
30 if (colorPanel.getMapSize()!=256) {
34 int red=0, green=0, blue=0;
35 GenericDialog gd =
new GenericDialog(
"LUT Editor");
36 Panel buttonPanel =
new Panel(
new GridLayout(4, 1, 0, 5));
37 openButton =
new Button(
"Open...");
38 openButton.addActionListener(
this);
39 buttonPanel.add(openButton);
40 saveButton =
new Button(
"Save...");
41 saveButton.addActionListener(
this);
42 buttonPanel.add(saveButton);
43 resizeButton =
new Button(
"Set...");
44 resizeButton.addActionListener(
this);
45 buttonPanel.add(resizeButton);
46 invertButton =
new Button(
"Invert...");
47 invertButton.addActionListener(
this);
48 buttonPanel.add(invertButton);
49 Panel panel =
new Panel();
50 panel.add(colorPanel);
51 panel.add(buttonPanel);
52 gd.addPanel(panel, GridBagConstraints.CENTER,
new Insets(10, 0, 0, 0));
54 if (gd.wasCanceled()){
55 colorPanel.cancelLUT();
58 colorPanel.applyLUT();
65 public void actionPerformed(ActionEvent e) {
66 Object source = e.getSource();
67 if (source==openButton)
69 else if (source==saveButton)
71 else if (source==resizeButton)
73 else if (source==invertButton)
79 class ColorPanel
extends Panel implements MouseListener, MouseMotionListener{
80 static final int entryWidth=12, entryHeight=12;
83 Color c[] =
new Color[256];
86 IndexColorModel origin;
87 private ImagePlus imp;
88 private int[] xSize =
new int[256], redY, greenY, blueY;
89 private int mapSize, x, y, initialC = -1, finalC = -1;
90 private byte[] reds, greens, blues;
91 private boolean updateLut;
92 private static String[] choices = {
"Replication",
"Interpolation",
"Spline Fitting"};
93 private static String scaleMethod = choices[1];
95 ColorPanel(ImagePlus imp) {
99 public void setup(ImagePlus imp) {
105 IndexColorModel cm = (IndexColorModel)imp.getProcessor().getColorModel();
107 mapSize = cm.getMapSize();
108 reds =
new byte[256];
109 greens =
new byte[256];
110 blues =
new byte[256];
112 cm.getGreens(greens);
114 addMouseListener(
this);
115 addMouseMotionListener(
this);
116 for(
int index = 0; index < mapSize; index++)
117 c[index] =
new Color(reds[index]&255, greens[index]&255, blues[index]&255);
119 public Dimension getPreferredSize() {
120 return new Dimension(columns*entryWidth, rows*entryHeight);
122 public Dimension getMinimumSize() {
123 return new Dimension(columns*entryWidth, rows*entryHeight);
125 int getMouseZone(
int x,
int y){
126 int horizontal = (int)x/entryWidth;
127 int vertical = (int)y/entryHeight;
128 int index = (columns*vertical + horizontal);
131 public void colorRamp() {
132 if (initialC>finalC) {
137 float difference = finalC - initialC+1;
138 int start = (byte)c[initialC].getRed()&255;
139 int end = (byte)c[finalC].getRed()&255;
140 float rstep = (end-start)/difference;
141 for(
int index = initialC; index <= finalC; index++)
142 reds[index] = (byte)(start+ (index-initialC)*rstep);
144 start = (byte)c[initialC].getGreen()&255;
145 end = (byte)c[finalC].getGreen()&255;
146 float gstep = (end-start)/difference;
147 for(
int index = initialC; index <= finalC; index++)
148 greens[index] = (byte)(start + (index-initialC)*gstep);
150 start = (byte)c[initialC].getBlue()&255;
151 end = (byte)c[finalC].getBlue()&255;
152 float bstep = (end-start)/difference;
153 for(
int index = initialC; index <= finalC; index++)
154 blues[index] = (byte)(start + (index-initialC)*bstep);
155 for (
int index = initialC; index <= finalC; index++)
156 c[index] =
new Color(reds[index]&255, greens[index]&255, blues[index]&255);
160 public void mousePressed(MouseEvent e){
163 initialC = getMouseZone(x,y);
166 public void mouseReleased(MouseEvent e){
169 finalC = getMouseZone(x,y);
170 if(initialC>=mapSize&&finalC>=mapSize) {
171 initialC = finalC = -1;
174 if(initialC>=mapSize)
175 initialC = mapSize-1;
180 if (initialC == finalC) {
182 ColorChooser cc =
new ColorChooser(
"Color at Entry " + (finalC) , c[finalC] ,
false);
183 c[finalC] = cc.getColor();
184 if (c[finalC]==null){
190 ColorChooser icc =
new ColorChooser(
"Initial Entry (" + (initialC)+
")" , c[initialC] ,
false);
191 c[initialC] = icc.getColor();
192 if (c[initialC]==null){
194 initialC = finalC = -1;
198 ColorChooser fcc =
new ColorChooser(
"Final Entry (" + (finalC)+
")" , c[finalC] ,
false);
199 c[finalC] = fcc.getColor();
200 if (c[finalC]==null){
202 initialC = finalC = -1;
207 initialC = finalC = -1;
211 public void mouseClicked(MouseEvent e){}
212 public void mouseEntered(MouseEvent e){}
213 public void mouseExited(MouseEvent e){}
215 public void mouseDragged(MouseEvent e){
218 finalC = getMouseZone(x,y);
222 public void mouseMoved(MouseEvent e) {
225 int entry = getMouseZone(x,y);
227 int red = reds[entry]&255;
228 int green = greens[entry]&255;
229 int blue = blues[entry]&255;
230 IJ.showStatus(
"index=" + entry +
", color=" + red +
"," + green +
"," + blue);
242 IndexColorModel cm = (IndexColorModel)imp.getProcessor().getColorModel();
246 cm.getGreens(greens);
248 for(
int i=0; i<mapSize; i++)
249 c[i] =
new Color(reds[i]&255, greens[i]&255, blues[i]&255);
253 byte[] reds2 =
new byte[mapSize];
254 byte[] greens2 =
new byte[mapSize];
255 byte[] blues2 =
new byte[mapSize];
256 for (
int i=0; i<mapSize; i++) {
257 reds2[i] = (byte)(reds[mapSize-i-1]&255);
258 greens2[i] = (byte)(greens[mapSize-i-1]&255);
259 blues2[i] = (byte)(blues[mapSize-i-1]&255);
261 reds=reds2; greens=greens2; blues=blues2;
262 for(
int i=0; i<mapSize; i++)
263 c[i] =
new Color(reds[i]&255, greens[i]&255, blues[i]&255);
269 GenericDialog sgd =
new GenericDialog(
"LUT Editor");
270 sgd.addNumericField(
"Number of Colors:", mapSize, 0);
271 sgd.addChoice(
"Scale Using:", choices, scaleMethod);
273 if (sgd.wasCanceled()){
277 int newSize = (int)sgd.getNextNumber();
278 if (newSize<2) newSize = 2;
279 if (newSize>256) newSize =256;
280 scaleMethod = sgd.getNextChoice();
281 scale(reds, greens, blues, newSize);
283 for(
int i=0; i<mapSize; i++)
284 c[i] =
new Color(reds[i]&255, greens[i]&255, blues[i]&255);
289 void scale(byte[] reds, byte[] greens, byte[] blues,
int newSize) {
290 if (newSize==mapSize)
292 else if (newSize<mapSize || scaleMethod.equals(choices[0]))
293 scaleUsingReplication(reds, greens, blues, newSize);
294 else if (scaleMethod.equals(choices[1]))
295 scaleUsingInterpolation(reds, greens, blues, newSize);
297 scaleUsingSplineFitting(reds, greens, blues, newSize);
300 void scaleUsingReplication(byte[] reds, byte[] greens, byte[] blues,
int newSize) {
301 byte[] reds2 =
new byte[256];
302 byte[] greens2 =
new byte[256];
303 byte[] blues2 =
new byte[256];
304 for(
int i = 0; i < mapSize; i++) {
306 greens2[i] = greens[i];
307 blues2[i] = blues[i];
309 for(
int i = 0; i < newSize; i++) {
310 int index =(int)( i*((
double)mapSize/newSize));
311 reds[i] = reds2[index];
312 greens[i] = greens2[index];
313 blues[i] = blues2[index];
317 void scaleUsingInterpolation(byte[] reds, byte[] greens, byte[] blues,
int newSize) {
318 int[] r =
new int[mapSize];
319 int[] g =
new int[mapSize];
320 int[] b =
new int[mapSize];
321 for(
int i = 0; i<mapSize; i++) {
323 g[i] = greens[i]&255;
326 double scale = (double)(mapSize-1)/(newSize-1);
329 for (
int i=0; i<newSize; i++) {
332 if (i2==mapSize) i2 = mapSize-1;
333 fraction = i*scale - i1;
335 reds[i] = (byte)((1.0-fraction)*r[i1] + fraction*r[i2]);
336 greens[i] = (byte)((1.0-fraction)*g[i1] + fraction*g[i2]);
337 blues[i] = (byte)((1.0-fraction)*b[i1] + fraction*b[i2]);
341 void scaleUsingSplineFitting(byte[] reds, byte[] greens, byte[] blues,
int newSize) {
343 int[] reds2 =
new int[mapSize];
344 int[] greens2 =
new int[mapSize];
345 int[] blues2 =
new int[mapSize];
346 for(
int i=0; i<mapSize; i++) {
347 reds2[i] = reds[i]&255;
348 greens2[i] = greens[i]&255;
349 blues2[i] = blues[i]&255;
351 int[] xValues =
new int[mapSize];
352 for(
int i = 0; i < mapSize; i++) {
353 xValues[i] = (int)(i*(
double)newSize/(mapSize-1));
356 SplineFitter sfReds =
new SplineFitter(xValues, reds2, mapSize);
357 SplineFitter sfGreens =
new SplineFitter(xValues, greens2, mapSize);
358 SplineFitter sfBlues =
new SplineFitter(xValues, blues2, mapSize);
359 for(
int i = 0; i < newSize; i++) {
360 double v = Math.round(sfReds.evalSpline(xValues, reds2, mapSize, i));
361 if (v<0.0) v=0.0;
if (v>255.0) v=255.0; reds[i] = (byte)v;
362 v = Math.round(sfGreens.evalSpline(xValues, greens2, mapSize, i));
363 if (v<0.0) v=0.0;
if (v>255.0) v=255.0; greens[i] = (byte)v;
364 v = Math.round(sfBlues.evalSpline(xValues, blues2, mapSize, i));
365 if (v<0.0) v=0.0;
if (v>255.0) v=255.0; blues[i] = (byte)v;
369 public void cancelLUT() {
372 origin.getReds(reds);
373 origin.getGreens(greens);
374 origin.getBlues(blues);
379 public void applyLUT() {
380 byte[] reds2=reds, greens2=greens, blues2=blues;
382 reds2 =
new byte[256];
383 greens2 =
new byte[256];
384 blues2 =
new byte[256];
385 for(
int i = 0; i < mapSize; i++) {
387 greens2[i] = greens[i];
388 blues2[i] = blues[i];
390 scale(reds2, greens2, blues2, 256);
392 ColorModel cm =
new IndexColorModel(8, 256, reds2, greens2, blues2);
393 ImageProcessor ip = imp.getProcessor();
394 ip.setColorModel(cm);
398 public void update(Graphics g) {
402 public void paint(Graphics g) {
408 for (
int y=0; y<rows; y++) {
409 for (
int x=0; x<columns; x++) {
411 g.setColor(Color.lightGray);
412 g.fillRect(x*entryWidth, y*entryHeight, entryWidth, entryHeight);
413 }
else if (((index <= finalC) && (index >= initialC)) || ((index >= finalC) && (index <= initialC))){
414 g.setColor(c[index].brighter());
415 g.fillRect(x*entryWidth, y*entryHeight, entryWidth, entryHeight);
416 g.setColor(Color.white);
417 g.drawRect((x*entryWidth), (y*entryHeight), entryWidth, entryHeight);
418 g.setColor(Color.black);
419 g.drawLine((x*entryWidth)+entryWidth-1, (y*entryHeight), (x*entryWidth)+entryWidth-1, (y*entryWidth)+entryHeight);
420 g.drawLine((x*entryWidth), (y*entryHeight)+entryHeight-1, (x*entryWidth)+entryWidth-1, (y*entryHeight)+entryHeight-1);
421 g.setColor(Color.white);
423 g.setColor(c[index]);
424 g.fillRect(x*entryWidth, y*entryHeight, entryWidth, entryHeight);
425 g.setColor(Color.white);
426 g.drawRect((x*entryWidth), (y*entryHeight), entryWidth-1, entryHeight-1);
427 g.setColor(Color.black);
428 g.drawLine((x*entryWidth), (y*entryHeight), (x*entryWidth)+entryWidth-1, (y*entryWidth));
429 g.drawLine((x*entryWidth), (y*entryHeight), (x*entryWidth), (y*entryHeight)+entryHeight-1);