@@ -22,6 +22,7 @@ public class ContrastAdjuster extends PlugInDialog implements Runnable,
2222 static final int AUTO_THRESHOLD = 5000 ;
2323 static final String [] channelLabels = {"Red" , "Green" , "Blue" , "Cyan" , "Magenta" , "Yellow" , "All" };
2424 static final String [] altChannelLabels = {"Channel 1" , "Channel 2" , "Channel 3" , "Channel 4" , "Channel 5" , "Channel 6" , "All" };
25+ static final String [] greyChannelLabels = {"LUT level" };
2526 static final int [] channelConstants = {4 , 2 , 1 , 3 , 5 , 6 , 7 };
2627
2728 ContrastPlot plot = new ContrastPlot ();
@@ -55,6 +56,8 @@ public class ContrastAdjuster extends PlugInDialog implements Runnable,
5556 Font sanFont = IJ .font12 ;
5657 int channels = 7 ; // RGB
5758 Choice choice ;
59+ Checkbox logHistCheckbox ;
60+ boolean isLogHist = false ;
5861 private String blankLabel8 = "--------" ;
5962 private String blankLabel12 = "------------" ;
6063 private double scale = Prefs .getGuiScale ();
@@ -127,6 +130,14 @@ else if (balance) {
127130 blankLabel8 = " " ;
128131 }
129132
133+ // log histogram scale checkbox
134+ logHistCheckbox = new Checkbox ("Log scale" );
135+ logHistCheckbox .setState (isLogHist );
136+ logHistCheckbox .addItemListener (this );
137+ c .gridy = y ++;
138+ gridbag .setConstraints (logHistCheckbox , c );
139+ add (logHistCheckbox );
140+
130141 // min slider
131142 if (!windowLevel ) {
132143 minSlider = new Scrollbar (Scrollbar .HORIZONTAL , sliderRange /2 , 1 , 0 , sliderRange );
@@ -256,6 +267,9 @@ void addBalanceChoices() {
256267 if (imp !=null && imp .isComposite ()) {
257268 for (int i =0 ; i <altChannelLabels .length ; i ++)
258269 choice .addItem (altChannelLabels [i ]);
270+ } else if (imp !=null && ((imp .getType () == ImagePlus .GRAY8 ) || (imp .getType () == ImagePlus .GRAY16 ) || (imp .getType () == ImagePlus .GRAY32 ))) {
271+ for (int i =0 ; i <greyChannelLabels .length ; i ++)
272+ choice .addItem (greyChannelLabels [i ]);
259273 } else {
260274 for (int i =0 ; i <channelLabels .length ; i ++)
261275 choice .addItem (channelLabels [i ]);
@@ -387,15 +401,22 @@ else if (newSliderRange>=1280)
387401 if (imp .isComposite ()) {
388402 int channel = imp .getChannel ();
389403 if (channel <=4 ) {
404+ choice .removeAll ();
405+ addBalanceChoices ();
390406 choice .select (channel -1 );
391407 channels = channelConstants [channel -1 ];
392408 }
393- if (choice .getItem (0 ).equals ("Red" )) {
409+ if (!choice .getItem (0 ).equals ("Channel 1" )) { // if the choice is wrong
410+ choice .removeAll ();
411+ addBalanceChoices ();
412+ }
413+ } else if ((imp .getType () == ImagePlus .GRAY8 ) || (imp .getType () == ImagePlus .GRAY16 ) || (imp .getType () == ImagePlus .GRAY32 )) { // grey image
414+ if (!choice .getItem (0 ).equals ("LUT level" )) { // if the choice is wrong
394415 choice .removeAll ();
395416 addBalanceChoices ();
396417 }
397418 } else { // not composite
398- if (choice .getItem (0 ).equals ("Channel 1 " )) {
419+ if (! choice .getItem (0 ).equals ("Red " )) { // if the choice is wrong
399420 choice .removeAll ();
400421 addBalanceChoices ();
401422 }
@@ -607,6 +628,7 @@ void reset(ImagePlus imp, ImageProcessor ip) {
607628 void plotHistogram (ImagePlus imp ) {
608629 ImageStatistics stats ;
609630 if (balance && (channels ==4 || channels ==2 || channels ==1 ) && imp .getType ()==ImagePlus .COLOR_RGB ) {
631+ setTitle ("Color" );
610632 int w = imp .getWidth ();
611633 int h = imp .getHeight ();
612634 byte [] r = new byte [w *h ];
@@ -623,17 +645,19 @@ else if (channels==1)
623645 ImageProcessor ip = new ByteProcessor (w , h , pixels , null );
624646 stats = ImageStatistics .getStatistics (ip , 0 , imp .getCalibration ());
625647 } else {
648+ if (balance ) {setTitle ("Color" );}
649+ if (balance && ((imp .getType () == ImagePlus .GRAY8 ) || (imp .getType () == ImagePlus .GRAY16 ) || (imp .getType () == ImagePlus .GRAY32 )) && !imp .isComposite ()) { // image is grey
650+ setTitle ("LUT Color" );
651+ }
626652 int range = imp .getType ()==ImagePlus .GRAY16 ?ImagePlus .getDefault16bitRange ():0 ;
627653 if (range !=0 && imp .getProcessor ().getMax ()==Math .pow (2 ,range )-1 && !(imp .getCalibration ().isSigned16Bit ())) {
628654 ImagePlus imp2 = new ImagePlus ("Temp" , imp .getProcessor ());
629655 stats = new StackStatistics (imp2 , 256 , 0 , Math .pow (2 ,range ));
630656 } else
631657 stats = imp .getStatistics ();
632658 }
633- Color color = Color .gray ;
634- if (imp .isComposite () && !(balance &&channels ==7 ))
635- color = ((CompositeImage )imp ).getChannelColor ();
636- plot .setHistogram (stats , color );
659+ // Default histogram color for images without LUT is now defined in the setHistogram method
660+ plot .setHistogram (stats , isLogHist );
637661 }
638662
639663 void apply (ImagePlus imp , ImageProcessor ip ) {
@@ -1146,6 +1170,7 @@ void doUpdate() {
11461170 case BRIGHTNESS : adjustBrightness (imp , ip , bvalue ); break ;
11471171 case CONTRAST : adjustContrast (imp , ip , cvalue ); break ;
11481172 }
1173+ plotHistogram (imp );
11491174 updatePlot ();
11501175 updateLabels (imp );
11511176 if ((IJ .shiftKeyDown ()||(balance &&channels ==7 )) && imp .isComposite ())
@@ -1186,19 +1211,35 @@ public void windowActivated(WindowEvent e) {
11861211 }
11871212
11881213 public synchronized void itemStateChanged (ItemEvent e ) {
1189- int index = choice .getSelectedIndex ();
1190- channels = channelConstants [index ];
1191- ImagePlus imp = WindowManager .getCurrentImage ();
1192- if (imp !=null && imp .isComposite ()) {
1193- if (index +1 <=imp .getNChannels ())
1194- imp .setPosition (index +1 , imp .getSlice (), imp .getFrame ());
1195- else {
1196- choice .select (channelLabels .length -1 );
1197- channels = 7 ;
1214+ Object source = e .getSource ();
1215+ if (source ==logHistCheckbox ) {
1216+ isLogHist =logHistCheckbox .getState ();
1217+ // IJ.log("log state changed");
1218+ ImagePlus imp = WindowManager .getCurrentImage ();
1219+ if (imp !=null ) {
1220+ // IJ.log("now updating histogram from itemStateChanged "+imp);
1221+ plotHistogram (imp );
1222+ updatePlot ();
1223+ updateLabels (imp );
1224+ }
1225+ }
1226+ else {
1227+ int index = choice .getSelectedIndex ();
1228+ channels = channelConstants [index ];
1229+ ImagePlus imp = WindowManager .getCurrentImage ();
1230+ if (imp !=null ) {
1231+ if (imp .isComposite ()) {
1232+ if (index +1 <=imp .getNChannels ())
1233+ imp .setPosition (index +1 , imp .getSlice (), imp .getFrame ());
1234+ else {
1235+ choice .select (channelLabels .length -1 );
1236+ channels = 7 ;
1237+ }
1238+ } else {
1239+ imp .getProcessor ().snapshot ();
1240+ doReset = true ;
1241+ }
11981242 }
1199- } else {
1200- imp .getProcessor ().snapshot ();
1201- doReset = true ;
12021243 }
12031244 notify ();
12041245 }
@@ -1221,7 +1262,7 @@ public static void update() {
12211262
12221263
12231264class ContrastPlot extends Canvas implements MouseListener {
1224-
1265+ Color [] hColors ;
12251266 static final int WIDTH =128 , HEIGHT =64 ;
12261267 double defaultMin = 0 ;
12271268 double defaultMax = 255 ;
@@ -1238,6 +1279,8 @@ class ContrastPlot extends Canvas implements MouseListener {
12381279
12391280 public ContrastPlot () {
12401281 addMouseListener (this );
1282+ width = (int )(width *1.3 ); // increase size
1283+ height = (int )(height *1.3 ); // increase size
12411284 if (scale >1.0 ) {
12421285 width = (int )(width *scale );
12431286 height = (int )(height *scale );
@@ -1251,9 +1294,36 @@ public Dimension getPreferredSize() {
12511294 return new Dimension (width +1 , height +1 );
12521295 }
12531296
1254- void setHistogram (ImageStatistics stats , Color color ) {
1255- this .color = color ;
1297+ void setHistogram (ImageStatistics stats , boolean isLogHist ) {
12561298 histogram = stats .histogram ;
1299+ if (isLogHist ) {
1300+ for (int j =0 ;j <256 ;j ++) {
1301+ histogram [j ]=(int )(Math .log (histogram [j ])*100 );
1302+ }
1303+ }
1304+ ImagePlus imp = WindowManager .getCurrentImage ();
1305+ hColors = new Color [256 ];
1306+ for (int i =0 ; i <256 ; i ++) { // set the default histogram color when there is no LUT
1307+ hColors [i ] = new Color (110 , 110 ,150 );
1308+ }
1309+ int impType = imp .getType ();
1310+ if ((impType == ImagePlus .GRAY8 ) || (impType == ImagePlus .GRAY16 ) || (impType == ImagePlus .GRAY32 )) { //if image has LUT
1311+ ImageProcessor ip = imp .getProcessor ();
1312+ ColorModel cm = ip .getColorModel ();
1313+ IndexColorModel icm = (IndexColorModel )cm ;
1314+ int mapSize = icm .getMapSize ();
1315+ if (mapSize !=256 )
1316+ return ;
1317+ byte [] red = new byte [256 ];
1318+ byte [] green = new byte [256 ];
1319+ byte [] blue = new byte [256 ];
1320+ icm .getReds (red );
1321+ icm .getGreens (green );
1322+ icm .getBlues (blue );
1323+ for (int i =0 ; i <256 ; i ++) {
1324+ hColors [i ] = new Color (red [i ]&255 , green [i ]&255 , blue [i ]&255 );
1325+ }
1326+ }
12571327 if (histogram .length !=256 ) {
12581328 histogram =null ;
12591329 return ;
@@ -1271,11 +1341,16 @@ void setHistogram(ImageStatistics stats, Color color) {
12711341 if ((histogram [i ]>maxCount2 ) && (i !=mode ))
12721342 maxCount2 = histogram [i ];
12731343 }
1274- hmax = stats .maxCount ;
1344+ if (isLogHist ) {
1345+ hmax =(int )(Math .log (stats .maxCount )*100 );
1346+ } else {
1347+ hmax = stats .maxCount ;
1348+ }
12751349 if ((hmax >(maxCount2 *2 )) && (maxCount2 !=0 )) {
12761350 hmax = (int )(maxCount2 *1.5 );
12771351 histogram [mode ] = hmax ;
12781352 }
1353+
12791354 os = null ;
12801355 }
12811356
@@ -1284,9 +1359,17 @@ public void update(Graphics g) {
12841359 }
12851360
12861361 public void paint (Graphics g ) {
1287- int x1 , y1 , x2 , y2 ;
1362+ int x1 , y1 , x2 , y2 ,j ,j1 ,j2 ;
1363+ double colscale ;
12881364 double scale = (double )width /(defaultMax -defaultMin );
12891365 double slope = 0.0 ;
1366+ j1 =(int )((min -defaultMin )/(defaultMax -defaultMin )*255 );
1367+ j2 =(int )((max -defaultMin )/(defaultMax -defaultMin )*255 );
1368+ if (j2 >j1 ) {
1369+ colscale =255.0 /(j2 -j1 );
1370+ } else {
1371+ colscale =1 ;
1372+ }
12901373 if (max !=min )
12911374 slope = height /(max -min );
12921375 if (min >=defaultMin ) {
@@ -1315,11 +1398,20 @@ public void paint(Graphics g) {
13151398 osg = os .getGraphics ();
13161399 osg .setColor (Color .white );
13171400 osg .fillRect (0 , 0 , width , height );
1318- osg .setColor (color );
13191401 double scale2 = width /256.0 ;
13201402 for (int i = 0 ; i < 256 ; i ++) {
13211403 int x =(int )(i *scale2 );
1322- osg .drawLine (x , height , x , height - ((int )(height *histogram [i ])/hmax ));
1404+ j =(int ) ((i -j1 )*colscale );
1405+ if (i <j1 ) {j =0 ;};
1406+ if (i >j2 ) {j =255 ;};
1407+ // IJ.log("--> "+String.valueOf(j1)+" "+String.valueOf(j2)+" "+String.valueOf(i)+" "+String.valueOf(j));
1408+ if (hColors !=null )
1409+ osg .setColor (hColors [j ]);
1410+ int y = height - ((int )(height *histogram [i ])/hmax );
1411+ osg .drawLine (x , height , x , y );
1412+ osg .setColor (Color .black );
1413+ osg .fillRect (x , y , 1 , 1 );
1414+ //IJ.log("--> "+String.valueOf(i)+" "+String.valueOf(x)+" "+String.valueOf(histogram[i])+" "+String.valueOf(height - ((int)(height*histogram[i])/hmax)));
13231415 }
13241416 osg .dispose ();
13251417 }
@@ -1360,3 +1452,4 @@ public Dimension getPreferredSize() {
13601452} // TrimmedLabel class
13611453
13621454
1455+
0 commit comments