Ignore:
Timestamp:
02/01/12 18:30:55 (8 years ago)
Author:
aivar
Message:

Improved setting the LUT bounds with the histogram tool.

Location:
trunk/projects/slim-plugin/src/main/java/imagej/slim/histogram
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/projects/slim-plugin/src/main/java/imagej/slim/histogram/HistogramData.java

    r7875 r7879  
    99/** 
    1010 * Keeps an array of HistogramChannels for a given image.  Builds the  
    11  * histogram data as appropriate. 
     11 * histogram data as appropriate.  Handles updates as the fitted results are 
     12 * available.  Handles optional autoranging. 
    1213 *  
    13  * @author aivar 
     14 * @author Aivar Grislis 
    1415 */ 
    1516public class HistogramData { 
     
    2526    private double _minLUT; 
    2627    private double _maxLUT; 
     28    private double _minData; 
     29    private double _maxData; 
     30    private double _minDataCurrent; 
     31    private double _maxDataCurrent; 
    2732    private IHistogramDataListener _listener; 
    2833 
     
    4348        _minView = _maxView = 0.0f; 
    4449        _minLUT = _maxLUT = 0.0f; 
     50        _minData = _maxData = 0.0f; 
     51        _minDataCurrent = _maxDataCurrent = 0.0; 
    4552        _listener = null; 
    4653    } 
     
    97104     */ 
    98105    public void setAutoRange(boolean autoRange) { 
    99         _autoRange = autoRange; 
    100     } 
    101  
     106        update(autoRange, _combineChannels); 
     107    } 
     108     
    102109    /** 
    103110     * Gets whether or not histogram should combine all the channels. 
     
    115122     */ 
    116123    public void setCombineChannels(boolean combineChannels) { 
    117         _combineChannels = combineChannels; 
     124        update(_autoRange, combineChannels); 
    118125    } 
    119126     
     
    134141    public void setDisplayChannels(boolean displayChannels) { 
    135142        _displayChannels = displayChannels; 
     143    } 
     144 
     145    /* 
     146     * Helper function to update autoranging or channel combination. 
     147     */ 
     148    private void update(boolean autoRange, boolean combineChannels) { 
     149        if (_autoRange != autoRange || _combineChannels != combineChannels) { 
     150            double minView; 
     151            double maxView; 
     152            double minLUT; 
     153            double maxLUT; 
     154             
     155            _autoRange       = autoRange; 
     156            _combineChannels = combineChannels; 
     157             
     158            if (_autoRange) { 
     159                if (_combineChannels) { 
     160                    // LUT and view bounded by data for all channels 
     161                    minLUT = _minData; 
     162                    maxLUT = _maxData; 
     163                     
     164                    minView = minLUT; 
     165                    maxView = maxLUT; 
     166                } 
     167                else { 
     168                    // LUT is bounded by data for current channel 
     169                    minLUT = _minDataCurrent; 
     170                    maxLUT = _maxDataCurrent; 
     171                     
     172                    if (_displayChannels) { 
     173                        minView = _minData; 
     174                        maxView = _maxData; 
     175                    } 
     176                    else { 
     177                        minView = minLUT; 
     178                        maxView = maxLUT; 
     179                    } 
     180                } 
     181                 
     182                // did anything really change? 
     183                if (_minView != minView || _maxView != maxView 
     184                        || _minLUT != minLUT || _maxLUT != maxLUT) { 
     185                    _minView = minView; 
     186                    _maxView = maxView; 
     187                    _minLUT = minLUT; 
     188                    _maxLUT = maxLUT; 
     189 
     190                    // update listener, if any 
     191                    if (null != _listener) { 
     192                        _listener.minMaxChanged(minView, maxView, minLUT, maxLUT); 
     193                    } 
     194                } 
     195            } 
     196        } 
    136197    } 
    137198 
     
    174235        _minLUT = min; 
    175236        _maxLUT = max; 
     237        redisplay(); 
    176238    } 
    177239 
     
    185247     * @return min and max of the LUT 
    186248     */ 
     249    //TODO these recalcHistogram events need to be synchronized so that they 
     250    // don't step on other ways to change min/maxLUT/View 
     251    // Perhaps this class should have a synch object that also has a getter. 
    187252    public double[] recalcHistogram() { 
    188253        double minData; 
     
    241306        _minView = minData; 
    242307        _maxView = maxData; 
     308         
     309        _minData = minData; 
     310        _maxData = maxData; 
     311         
     312        _minDataCurrent = minDataCurrent; 
     313        _maxDataCurrent = maxDataCurrent; 
    243314 
    244315        if (null != _listener) { 
     
    246317        } 
    247318 
    248         return new double[] { minLUT, maxLUT }; 
     319        return new double[] { _minLUT, _maxLUT }; 
    249320    } 
    250321 
  • trunk/projects/slim-plugin/src/main/java/imagej/slim/histogram/HistogramPanel.java

    r7847 r7879  
    209209    /** 
    210210     * Changes cursors and redraws.  Note that when they are both null no 
    211      * cursor is diaplayed. 
     211     * cursor is diaplayed.  Otherwise if one is null only the other value 
     212     * changes. 
    212213     *  
    213      * @param minCursor 
    214      * @param maxCursor  
     214     * @param minCursor null or minimum cursor position in pixels 
     215     * @param maxCursor null or maximum cursor position in pixels 
    215216     */ 
    216217    public void setCursors(Integer minCursor, Integer maxCursor) { 
    217218        synchronized (_synchObject) { 
    218             _minCursor = minCursor; 
    219             _maxCursor = maxCursor; 
    220             if (null == _minCursor && null == _maxCursor) { 
    221                 _draggingMinCursor = _draggingMaxCursor = false; 
     219            if (null == minCursor) { 
     220                if (null == maxCursor) { 
     221                    // both null; turn off cursors 
     222                    _draggingMinCursor = _draggingMaxCursor = false; 
     223                    _minCursor = _maxCursor = null; 
     224                } 
     225                else { 
     226                    // setting just max cursor 
     227                    _maxCursor = maxCursor; 
     228                } 
     229            } 
     230            else if (null == maxCursor) { 
     231                // setting just min cursor 
     232                _minCursor = minCursor; 
    222233            } 
    223234            else { 
     235                // setting both cursors 
     236                _minCursor = minCursor; 
     237                _maxCursor = maxCursor; 
     238                 
    224239                // the cursors actually bracket the specified pixels 
    225240                --_minCursor; 
  • trunk/projects/slim-plugin/src/main/java/imagej/slim/histogram/HistogramTool.java

    r7875 r7879  
    5858     * Constructor, handles layout and wiring. 
    5959     */ 
    60     private HistogramTool() { 
     60    private HistogramTool() { //TODO ARG how do you pass this in if it is a singleton?  (cf getInstance() below) 
     61        //TODO ARG how is this a singleton if there are two flavors of it? 
     62        //TODO ARG need to be able to close this window and have it pop back up as needed 
     63        // boolean hasChannels) { 
    6164        // create the histogram and color bar display panels 
    6265        _histogramPanel = new HistogramPanel(WIDTH, INSET, HISTOGRAM_HEIGHT); 
     
    6467        _colorBarPanel = new ColorBarPanel(WIDTH, INSET, COLORBAR_HEIGHT); 
    6568        _colorBarPanel.setLUT(getLUT()); 
    66         _uiPanel = new UIPanel(false); // true); 
     69        boolean hasChannels = false; 
     70        _uiPanel = new UIPanel(hasChannels); 
    6771        _uiPanel.setListener(new UIPanelListener()); 
    6872 
     
    9195    /** 
    9296     * Gets an IndexColorModel by loading a hardcoded LUT file. 
    93      * Temporary expedient, belongs elsewhere. 
     97     * This is just a temporary expedient, really belongs elsewhere. 
    9498     *  
    9599     * @return  
     
    169173            double[] minMaxView = _histogramData.getMinMaxView(); 
    170174            double min = minMaxView[0]; 
     175            return min + pixelToValueRelative(pixel); 
     176        } 
     177    } 
     178     
     179    private double pixelToValueRelative(int pixel) { 
     180        synchronized (_synchObject) { 
     181            double[] minMaxView = _histogramData.getMinMaxView(); 
     182            double min = minMaxView[0]; 
    171183            double max = minMaxView[1]; 
    172             double value = (max - min) / PaletteFix.getSize(); 
    173             return (pixel - INSET) * value; 
     184            double valuePerPixel = (max - min) / PaletteFix.getSize(); 
     185            return pixel * valuePerPixel; 
    174186        } 
    175187    } 
     
    184196            double max = minMaxView[1]; 
    185197            int pixel = (int)(PaletteFix.getSize() * (value - min) / (max - min)); 
     198            System.out.println("valueToPixel(" + value + ") -> " + pixel); 
    186199            return pixel; 
    187200        } 
     
    207220    } 
    208221 
     222    /* 
     223     * Given a value representing the minimum or maximum cursor bound, 
     224     * calculates a pixel location for the cursor. 
     225     *  
     226     * @param max whether this is the maximum cursor or not 
     227     */ 
     228    private int cursorPixelFromValue(boolean max, double value) { 
     229        int pixel = INSET + valueToPixel(value); 
     230        if (max) { 
     231            // cursor brackets the value 
     232            ++pixel; 
     233        } 
     234        return pixel; 
     235    } 
     236 
    209237    /** 
    210238     * Inner class listens for changes during the fit. 
     
    216244                double minLUT, double maxLUT) { 
    217245            changed(minView, maxView, minLUT, maxLUT); 
     246            _uiPanel.setMinMaxLUT(minLUT, maxLUT); 
    218247        } 
    219248    } 
     
    236265        public void setMinMaxLUTPixels(int min, int max) { 
    237266            killTimer(); 
    238  
     267 System.out.println("setMinMaxLUTPixels(" + min + "," + max + ")"); 
    239268            // get new minimum and maximum values for LUT 
    240269            double minLUT = pixelToValue(min); 
    241             double maxLUT = pixelToValue(max); 
     270            double maxLUT = pixelToValue(max + 1); 
     271             
     272 System.out.println("setMinMaxLUTPixels values are " + minLUT + " " + maxLUT); 
     273  
     274 System.out.println("maxLut for max + 1 would be " + pixelToValue(max + 1)); 
     275 System.out.println("minLUT for min = 0 would be " + pixelToValue(0)); 
    242276             
    243277            // set min and max on UI panel 
     
    262296        @Override 
    263297        public void dragMinMaxPixels(int min, int max) { 
    264             System.out.println("dragMinMax(" + min + "," + max + ")"); 
    265             if (min < 0 || max >= PaletteFix.ADJUSTED_SIZE) { 
     298            if (min < 0 || max >= PaletteFix.getSize()) { 
    266299                // cursor is out of bounds, set up a periodic task to stretch 
    267300                // the bounds, if not already running 
     
    270303                } 
    271304                else { 
    272                     _dragPixels = max - PaletteFix.ADJUSTED_SIZE + 1; 
     305                    _dragPixels = max - PaletteFix.getSize() + 1; 
    273306                } 
    274307                if (null == _timer) { 
    275                     System.out.println("Schedule"); 
    276308                    _timer = new Timer(); 
    277309                    _timer.schedule(new PeriodicTask(), 0, TASK_PERIOD); 
     
    281313                // dragging within bounds now, kill the periodic task, if any 
    282314                killTimer(); 
    283                 _uiPanel.dragMinMaxLUT(pixelToValue(min), pixelToValue(max)); 
     315                double minLUT = pixelToValue(min); 
     316                double maxLUT = pixelToValue(max + 1); 
     317                _uiPanel.dragMinMaxLUT(minLUT, maxLUT); 
    284318            } 
    285319        } 
     
    308342            public void run() { 
    309343                // how much are we dragging, converted to our value 
    310                 double value = pixelToValue(_dragPixels); 
    311                 System.out.println("value " + value + " dp " + _dragPixels); 
     344                double value = pixelToValueRelative(_dragPixels); 
    312345                synchronized (_synchObject) { 
    313346                    // get current LUT bounds 
     
    329362                    } 
    330363 
    331                     // get updated histogram data & show it 
     364                    // update histogram data min and max view 
    332365                    _histogramData.setMinMaxView(minView, maxView); 
     366                     
     367                    // keep other cursor fixed 
     368                    int pixel; 
     369                    if (value < 0) { 
     370                        if (maxView != maxLUT) { 
     371                            pixel = cursorPixelFromValue(true, maxLUT); 
     372                            //pixel = valueToPixel(maxLUT); 
     373                            //System.out.println("PeriodicTask.run maxLUT is " + maxLUT + " cursor is at " + pixel); 
     374                            //_histogramPanel.setCursors(null, INSET + pixel + 1); //TODO ARG this is still a little bit off 
     375                            _histogramPanel.setCursors(null, pixel); //TODO ARG this is still a little off 
     376                        } 
     377                    } 
     378                    else { 
     379                        if (minView != minLUT) { 
     380                            pixel = cursorPixelFromValue(false, minLUT); 
     381                            //pixel = valueToPixel(minLUT); 
     382                            //System.out.println("PeriodicTask.run minLUT is " + minLUT + " cursor is at " + pixel); 
     383                            //_histogramPanel.setCursors(INSET + pixel, null); //TODO ARG this is still a little bit off 
     384                            _histogramPanel.setCursors(pixel, null); //TODO ARG this is still a little off 
     385   
     386                        } 
     387                    } 
     388                     
     389                    // get updated histogram data and show it                  
    333390                    int[] bins = _histogramData.binValues(PaletteFix.ADJUSTED_SIZE); 
    334391                    _histogramPanel.setBins(bins); 
    335392                    _colorBarPanel.setMinMax(minView, maxView, minLUT, maxLUT); 
    336                     System.out.println("set to " + minView + " " + maxView); 
     393                     
     394                    // update numbers in UI panel 
     395                    _uiPanel.dragMinMaxLUT(minLUT, maxLUT); 
    337396                } 
    338397            } 
     
    343402        @Override 
    344403        public void setAutoRange(boolean autoRange) { 
    345             System.out.println("HistogramTool.UIPanelListener.setAutoRange(" + autoRange + ")"); 
    346404            synchronized (_synchObject) { 
    347405                 _histogramData.setAutoRange(autoRange); 
    348             } 
    349  
    350             if (autoRange) { 
    351                 _histogramPanel.setCursors(null, null); 
    352                 //TODO calculate new bounds 
    353             } 
    354             else { 
    355                 //TODO if you are autoranging, not combining channels, but showing 
    356                 // all channels, these cursors would need to be calculated 
    357                 _histogramPanel.setCursors(INSET, INSET + WIDTH - 1); //TODO I was expecting INSET-1 here?? 
     406                  
     407                 if (autoRange) { 
     408                     //TODO ARG: 
     409                    // It is not always true that the cursors will be (null, null) 
     410                    // [same as (0, 254)], th3 exception happens if you are showing 
     411                    // all channels but only autoranging your channel. 
     412                    _histogramPanel.setCursors(null, null); 
     413                     
     414                  ///  _histogramData.recalcHistogram(); //TODO histogramData should just keep minData/maxData same as the others 
     415                 } 
     416                 else { 
     417                    //TODO if you are autoranging, not combining channels, but showing 
     418                    // all channels, these cursors would need to be calculated 
     419                    _histogramPanel.setCursors(INSET, INSET + WIDTH - 1); //TODO I was expecting INSET-1 here?? 
     420 
     421                 } 
    358422            } 
    359423        } 
     
    389453                 
    390454                synchronized (_synchObject) { 
    391                     // expand the view to fit the LUT 
     455                    // if necessary, expand the view to fit the LUT 
    392456                    double[] minMaxView = _histogramData.getMinMaxView(); 
    393457                    minView = Math.min(minLUT, minMaxView[0]); 
     
    395459                    _histogramData.setMinMaxView(minView, maxView); 
    396460                    _histogramData.setMinMaxLUT(minLUT, maxLUT); 
     461 
     462                    //TODO ARG this is quite a bit off: 
     463                    // note that if you stretch the bounds on one side you need 
     464                    // to adjust the position of the other side. 
     465                    _histogramPanel.setCursors(cursorPixelFromValue(false, minLUT), cursorPixelFromValue(true, maxLUT)); 
    397466                } 
    398467            } 
  • trunk/projects/slim-plugin/src/main/java/imagej/slim/histogram/PaletteFix.java

    r7844 r7879  
    6262    /** 
    6363     * Given a min and max specification for a 254-color palette, turns it into 
    64      * a 256-color palette min and max. 
     64     * a 256-color palette min and max.  Values below 254-color min are colored 
     65     * with below color and values above 254-color max are colored with above 
     66     * color. 
    6567     *  
    6668     * @param min 
     
    7072    public static double[] adjustMinMax(double min, double max) { 
    7173        double adjust = (max - min) / ADJUSTED_SIZE; 
     74         
     75        //TODO ARG ueed ADJUSTED_SIZE + 1 as a kludge: it made more black dots 
     76        //TODO ARG having - 1 appears to have the same result! 
     77        //TODO ARG tried + or - 0.5 
    7278        return new double[] { min - adjust, max + adjust }; 
    7379    } 
  • trunk/projects/slim-plugin/src/main/java/imagej/slim/histogram/UIPanel.java

    r7861 r7879  
    2525 */ 
    2626public class UIPanel extends JPanel { 
    27     private static final int DIGITS = 4; 
     27    private static final int DIGITS = 5; 
    2828    IUIPanelListener _listener; 
    2929    JCheckBox _autoRangeCheckBox; 
     
    6767                    } 
    6868                    catch (NumberFormatException exception) { 
     69                        // in the event of an error, just revert 
    6970                        _minTextField.setText("" + _minLUT); 
    7071                    } 
     
    8586                    } 
    8687                    catch (NumberFormatException exception) { 
     88                        // in the event of an error, just revert 
    8789                        _maxTextField.setText("" + _maxLUT); 
    8890                    } 
     
    174176     */ 
    175177    public void dragMinMaxLUT(double min, double max) { 
    176         System.out.println("UIPanel.dragMinMaxLUT"); 
     178        System.out.println("UIPanel.dragMinMaxLUT " + min + " " + max); 
    177179        showMinMaxLUT(min, max); 
    178180    } 
     
    185187     */ 
    186188    public void setMinMaxLUT(double min, double max) { 
    187         System.out.println("UIPanel.setMinMaxLUT"); 
     189        System.out.println("UIPanel.setMinMaxLUT " + min + " " + max); 
    188190        showMinMaxLUT(min, max); 
    189191        //TODO anything else?  if not combine these two methods 
Note: See TracChangeset for help on using the changeset viewer.