Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
CalibrationBar.java
1 package ij.plugin.filter;
2 //import ij.plugin.filter.PlugInFilter;
3 import ij.*;
4 import java.awt.*;
5 import java.awt.image.*;
6 import java.awt.event.*;
7 import java.io.*;
8 import java.awt.datatransfer.*;
9 import ij.gui.*;
10 import ij.process.*;
11 import ij.measure.Measurements;
12 import ij.plugin.filter.Analyzer;
13 import ij.text.TextWindow;
14 import ij.measure.*;
15 
27 public class CalibrationBar implements PlugInFilter {
28  final static int BAR_LENGTH = 128;
29  final static int BAR_THICKNESS = 12;
30  final static int XMARGIN = 10;
31  final static int YMARGIN = 10;
32  final static int WIN_HEIGHT = BAR_LENGTH;
33  final static int BOX_PAD = 0;
34  final static int LINE_WIDTH = 1;
35  static int nBins = 256;
36  static final String[] colors = {"White","Light Gray","Dark Gray","Black","Red","Green","Blue","Yellow","None"};
37  static final String[] locations = {"Upper Right","Lower Right","Lower Left", "Upper Left", "At Selection"};
38  static final int UPPER_RIGHT=0, LOWER_RIGHT=1, LOWER_LEFT=2, UPPER_LEFT=3, AT_SELECTION=4;
39 
40  static String fillColor = colors[0];
41  static String textColor = colors[3];
42  static String location = locations[UPPER_RIGHT];
43  static double zoom = 1;
44  static int numLabels = 5;
45  static int fontSize = 12;
46  static int decimalPlaces = 0;
47 
48  ImagePlus imp;
49  ImagePlus impOriginal;
50 
51  LiveDialog gd;
52 
53  ImageStatistics stats;
54  Calibration cal;
55  int[] histogram;
56  LookUpTable lut;
57  Image img;
58  Button setup, redraw, insert, unInsert;
59  Checkbox ne,nw,se,sw;
60  CheckboxGroup locGroup;
61  Label value, note;
62  int newMaxCount;
63  boolean logScale;
64  int win_width;
65  int userPadding = 0;
66  int fontHeight = 0;
67  boolean boldText = false;
68  Object backupPixels;
69  byte[] byteStorage;
70  int[] intStorage;
71  short[] shortStorage;
72  float[] floatStorage;
73  String boxOutlineColor = colors[8];
74  String barOutlineColor = colors[3];
75 
76  ImagePlus impData;
77  ImageProcessor ip;
78  String[] fieldNames = null;
79  int insetPad;
80  boolean decimalPlacesChanged;
81 
82  public int setup(String arg, ImagePlus imp) {
83  if(imp!=null) {
84  this.imp = imp;
85  impData = imp;
86  if(imp.getRoi()!=null)
87  location = locations[AT_SELECTION];
88  }
90  }
91 
92  public void run(ImageProcessor ipPassed) {
93  double mag = (imp!=null)?imp.getCanvas().getMagnification():1.0;
94  if (zoom<=1 && mag<1)
95  zoom = (double) 1.0/mag;
96  ip = ipPassed.duplicate().convertToRGB();
97  impOriginal = imp;
98  imp = new ImagePlus(imp.getTitle()+" with bar", ip);
99  imp.setCalibration(impData.getCalibration());
100  if(impOriginal.getRoi()!=null)
101  imp.setRoi(impOriginal.getRoi());
102  imp.show();
103  ip.snapshot();
104  insetPad = imp.getWidth()/50;
105  if (insetPad<4)
106  insetPad = 4;
107  updateColorBar();
108  if(!showDialog()) {
109  ip.reset();
110  this.imp.updateAndDraw();
111  return;
112  }
113  updateColorBar();
114 
115  }
116 
117  private void updateColorBar() {
118  ip.reset();
119  Roi roi = imp.getRoi();
120  if (roi!=null && location.equals(locations[AT_SELECTION])) {
121  Rectangle r = roi.getBounds();
122  drawColorBar(imp,r.x,r.y);
123  } else if( location.equals(locations[UPPER_LEFT]))
124  drawColorBar(imp,insetPad,insetPad);
125  else if(location.equals(locations[UPPER_RIGHT])) {
126  calculateWidth();
127  drawColorBar(imp,imp.getWidth()-insetPad-win_width,insetPad);
128  } else if( location.equals(locations[LOWER_LEFT]) )
129  drawColorBar(imp,insetPad,imp.getHeight() - (int)(WIN_HEIGHT*zoom + 2*(int)(YMARGIN*zoom)) - (int)(insetPad*zoom));
130  else if(location.equals(locations[LOWER_RIGHT])) {
131  calculateWidth();
132  drawColorBar(imp,imp.getWidth()-win_width-insetPad,
133  imp.getHeight() - (int)(WIN_HEIGHT*zoom + 2*(int)(YMARGIN*zoom)) - insetPad);
134  }
135 
136  this.imp.updateAndDraw();
137  }
138 
139  private boolean showDialog() {
140  gd = new LiveDialog("Calibration Bar");
141  gd.addChoice("Location:", locations, location);
142  gd.addChoice("Fill Color: ", colors, fillColor);
143  gd.addChoice("Label Color: ", colors, textColor);
144  gd.addNumericField("Number of Labels:", numLabels, 0);
145  gd.addNumericField("Decimal Places:", decimalPlaces, 0);
146  gd.addNumericField("Font Size:", fontSize, 0);
147  gd.addNumericField("Zoom Factor:", zoom, 1);
148  gd.addCheckbox("Bold Text", boldText);
149  gd.showDialog();
150  if (gd.wasCanceled())
151  return false;
152  location = gd.getNextChoice();
153  fillColor = gd.getNextChoice();
154  textColor = gd.getNextChoice();
155  numLabels = (int)gd.getNextNumber();
156  decimalPlaces = (int)gd.getNextNumber();
157  fontSize = (int)gd.getNextNumber();
158  zoom = (double)gd.getNextNumber();
159  boldText = gd.getNextBoolean();
160  return true;
161  }
162 
163  public void verticalColorBar(ImageProcessor ip, int x, int y, int thickness, int length) {
164  int width = thickness;
165  int height = length;
166  byte[] rLUT,gLUT,bLUT;
167  int mapSize = 0;
168  java.awt.image.ColorModel cm = lut.getColorModel();
169  if (cm instanceof IndexColorModel) {
170  IndexColorModel m = (IndexColorModel)cm;
171  mapSize = m.getMapSize();
172  rLUT = new byte[mapSize];
173  gLUT = new byte[mapSize];
174  bLUT = new byte[mapSize];
175  m.getReds(rLUT);
176  m.getGreens(gLUT);
177  m.getBlues(bLUT);
178  } else {
179  mapSize = 256;
180  rLUT = new byte[mapSize];
181  gLUT = new byte[mapSize];
182  bLUT = new byte[mapSize];
183  for (int i = 0; i < mapSize; i++) {
184  rLUT[i] = (byte)i;
185  gLUT[i] = (byte)i;
186  bLUT[i] = (byte)i;
187  }
188  }
189  double colors = mapSize;
190  int start = 0;
191  ImageProcessor ipOrig = impOriginal.getProcessor();
192  if (ipOrig instanceof ByteProcessor) {
193  int min = (int)ipOrig.getMin();
194  if (min<0) min = 0;
195  int max = (int)ipOrig.getMax();
196  if (max>255) max = 255;
197  colors = max-min+1;
198  start = min;
199  }
200  for (int i = 0; i<(int)(BAR_LENGTH*zoom); i++) {
201  int iMap = start + (int)Math.round((i*colors)/(BAR_LENGTH*zoom));
202  if (iMap>=mapSize)
203  iMap =mapSize - 1;
204 
205  ip.setColor(new Color(rLUT[iMap]&0xff, gLUT[iMap]&0xff, bLUT[iMap]&0xff));
206  int j = (int)(BAR_LENGTH*zoom) - i - 1;
207  ip.drawLine(x, j+y, thickness+x, j+y);
208  }
209 
210  Color c = getColor(barOutlineColor);
211  if (c != null) {
212  ip.setColor(c);
213  ip.moveTo(x,y);
214  ip.lineTo(x+width,y);
215  ip.lineTo(x+width,y+height);
216  ip.lineTo(x,y+height);
217  ip.lineTo(x,y);
218  }
219  }
220 
221  protected void drawColorBar(ImageProcessor ip, int xOffset, int yOffset) {
222  int x, y;
223 
224  ip.setColor(Color.black);
225  if (decimalPlaces == -1)
226  decimalPlaces = Analyzer.getPrecision();
227  x = (int)(XMARGIN*zoom) + xOffset;
228  y = (int)(YMARGIN*zoom) + yOffset;
229 
230  verticalColorBar(ip, x, y, (int)(BAR_THICKNESS*zoom), (int)(BAR_LENGTH*zoom) );
231  drawText(ip, x + (int)(BAR_THICKNESS*zoom), y, true);
232 
233  Color c = getColor(boxOutlineColor);
234  if (c != null && !fillColor.equals("None")) {
235  ip.setColor(c);
236  ip.setLineWidth(LINE_WIDTH);
237  ip.moveTo(xOffset+BOX_PAD,yOffset+BOX_PAD);
238  ip.lineTo(xOffset+win_width-BOX_PAD,yOffset+BOX_PAD);
239  ip.lineTo(xOffset+win_width-BOX_PAD,yOffset+(int)(WIN_HEIGHT*zoom + 2*(int)(YMARGIN*zoom))-BOX_PAD);
240  ip.lineTo(xOffset+BOX_PAD,yOffset+(int)(WIN_HEIGHT*zoom + 2*(int)(YMARGIN*zoom))-BOX_PAD);
241  ip.lineTo(xOffset+BOX_PAD,yOffset+BOX_PAD);
242  }
243 
244  }
245 
246  int drawText(ImageProcessor ip, int x, int y, boolean active) {
247 
248  Color c = getColor(textColor);
249  if (c == null)
250  return 0;
251  ip.setColor(c);
252 
253  double hmin = cal.getCValue(stats.histMin);
254  double hmax = cal.getCValue(stats.histMax);
255  double barStep = (double)(BAR_LENGTH*zoom) ;
256  if (numLabels > 2)
257  barStep /= (numLabels - 1);
258 
259  int fontType = boldText?Font.BOLD:Font.PLAIN;
260  Font font = null;
261  if(fontSize<9)
262  font = new Font("SansSerif", fontType, 9);
263  else
264  font = new Font("SansSerif", fontType, (int)( fontSize*zoom));
265  ip.setFont(font);
266  ip.setAntialiasedText(true);
267  int maxLength = 0;
268 
269  //Blank offscreen image for font metrics
270  Image img = GUI.createBlankImage(128, 64);
271  Graphics g = img.getGraphics();
272  FontMetrics metrics = g.getFontMetrics(font);
273  fontHeight = metrics.getHeight();
274 
275  for (int i = 0; i < numLabels; i++) {
276  double yLabelD = (int)(YMARGIN*zoom + BAR_LENGTH*zoom - i*barStep - 1);
277  int yLabel = (int)(Math.round( y + BAR_LENGTH*zoom - i*barStep - 1));
278  Calibration cal = impOriginal.getCalibration();
279  //s = cal.getValueUnit();
280  ImageProcessor ipOrig = impOriginal.getProcessor();
281  double min = ipOrig.getMin();
282  double max = ipOrig.getMax();
283  if (ipOrig instanceof ByteProcessor) {
284  if (min<0) min = 0;
285  if (max>255) max = 255;
286  }
287  if (cal.calibrated()) {
288  min = cal.getCValue((int)min);
289  max = cal.getCValue((int)max);
290  }
291 
292  if (!decimalPlacesChanged && decimalPlaces==0 && (int)max!=max)
293  decimalPlaces = 2;
294 
295  double grayLabel = min + (max-min)/(numLabels-1) * i;
296 
297  if (active)
298  ip.drawString(d2s(grayLabel), x + 5, yLabel + fontHeight/2);
299 
300  int iLength = metrics.stringWidth(d2s(grayLabel));
301  if(iLength > maxLength)
302  maxLength = iLength;
303 
304  }
305  return maxLength;
306  }
307 
308  String d2s(double d) {
309  return IJ.d2s(d,decimalPlaces);
310  }
311 
312  int getFontHeight() {
313  Image img = GUI.createBlankImage(64, 64); //dummy version to get fontHeight
314  Graphics g = img.getGraphics();
315  int fontType = boldText?Font.BOLD:Font.PLAIN;
316  Font font = new Font("SansSerif", fontType, (int) (fontSize*zoom) );
317  FontMetrics metrics = g.getFontMetrics(font);
318  return metrics.getHeight();
319  }
320 
321  Color getColor(String color) {
322  Color c = Color.white;
323  if (color.equals(colors[1]))
324  c = Color.lightGray;
325  else if (color.equals(colors[2]))
326  c = Color.darkGray;
327  else if (color.equals(colors[3]))
328  c = Color.black;
329  else if (color.equals(colors[4]))
330  c = Color.red;
331  else if (color.equals(colors[5]))
332  c = Color.green;
333  else if (color.equals(colors[6]))
334  c = Color.blue;
335  else if (color.equals(colors[7]))
336  c = Color.yellow;
337  else if (color.equals(colors[8]))
338  c = null;
339  return c;
340  }
341 
342  void calculateWidth() {
343  drawColorBar(imp, -1, -1);
344  }
345 
346  public void drawColorBar(ImagePlus imp, int x, int y) {
347  Roi roi = impOriginal.getRoi();
348  if (roi!=null)
349  impOriginal.killRoi();
350  stats = impOriginal.getStatistics(Measurements.MIN_MAX, nBins);
351  if (roi!=null)
352  impOriginal.setRoi(roi);
353  histogram = stats.histogram;
354  lut = impOriginal.createLut();
355  cal = impOriginal.getCalibration();
356 
357  int maxTextWidth = drawText(ip, 0, 0, false);
358  win_width = (int)(XMARGIN*zoom) + 5 + (int)(BAR_THICKNESS*zoom) + maxTextWidth + (int)((XMARGIN/2)*zoom);
359  if (x==-1 && y==-1)
360  return; // return if calculating width
361 
362  Color c = getColor(fillColor);
363  if (c != null) {
364  ip.setColor(c);
365  ip.setRoi(x, y, win_width, (int)(WIN_HEIGHT*zoom + 2*(int)(YMARGIN*zoom)) );
366  ip.fill();
367  }
368  ip.resetRoi();
369 
370  drawColorBar(ip,x,y);
371  imp.updateAndDraw();
372 
373  ip.setColor(Color.black);
374 
375  }
376 
377 
378  class LiveDialog extends GenericDialog {
379 
380  LiveDialog(String title) {
381  super(title);
382  }
383 
384  public void textValueChanged(TextEvent e) {
385 
386  if(fieldNames == null) {
387  fieldNames = new String[4];
388  for(int i=0;i<4;i++)
389  fieldNames[i] = ((TextField)numberField.elementAt(i)).getName();
390  }
391 
392  TextField tf = (TextField)e.getSource();
393  String name = tf.getName();
394  String value = tf.getText();
395 
396  if(value.equals(""))
397  return;
398 
399  int i=0;
400  boolean needsRefresh = false;
401 
402  if(name.equals(fieldNames[0])) {
403 
404  i = getValue( value ).intValue() ;
405  if(i<1)
406  return;
407  else {
408  needsRefresh = true;
409  numLabels = i;
410  }
411  } else if(name.equals(fieldNames[1])) {
412  i = getValue( value ).intValue() ;
413  if(i<0)
414  return;
415  else {
416  needsRefresh = true;
417  decimalPlaces = i;
418  decimalPlacesChanged = true;
419  }
420 
421  } else if(name.equals(fieldNames[2])) {
422  i = getValue( value ).intValue() ;
423  if(i<1)
424  return;
425  else {
426  needsRefresh = true;
427  fontSize = i;
428 
429  }
430 
431  } else if(name.equals(fieldNames[3])) {
432  double d = 0;
433  d = getValue( "0" + value ).doubleValue() ;
434  if(d<=0)
435  return;
436  else {
437  needsRefresh = true;
438  zoom = d;
439  }
440  }
441 
442  if(needsRefresh)
443  updateColorBar();
444  return;
445  }
446 
447  public void itemStateChanged(ItemEvent e) {
448  location = ( (Choice)(choice.elementAt(0)) ).getSelectedItem();
449  fillColor = ( (Choice)(choice.elementAt(1)) ).getSelectedItem();
450  textColor = ( (Choice)(choice.elementAt(2)) ).getSelectedItem();
451  boldText = ( (Checkbox)(checkbox.elementAt(0)) ).getState();
452  updateColorBar();
453  }
454 
455  } //LiveDialog inner class
456 
457 }