Results 1 to 12 of 12
  1. #1
    aianta is offline Member
    Join Date
    Apr 2011
    Posts
    63
    Rep Power
    0

    Default Interesting problem, variables reset after initialization

    I am currently working on getting some custom jpanels to draw some lines for me. the jpanel code is shown here:

    Java Code:
    import java.awt.Color;
    import java.awt.Graphics;
    import javax.swing.JPanel;
    
    public class HistogramJPanel extends JPanel {
    	
    	private int [] histogram;
    	private int displayFactor;
    	private Color paintColor;
    	private RGBHistogram input;
    	
    	public HistogramJPanel (RGBHistogram input){
    		
    		this.input = input;
    		this.histogram = input.getBandHistogram();
    		this.paintColor = input.getBandColor();
    		
    	}
    	
    	@Override
    	protected void paintComponent(Graphics g){
    		super.paintComponent(g);
    		
    		this.histogram = input.getBandHistogram();
    		
    		int max = 0;
    	
    		for (int i = 0; i < histogram.length; i++){
    			if (max < histogram[i])
    				max = histogram[i];
    		}
    		
    		displayFactor = max/150;
    	
    		g.setColor(paintColor);
    			
    		for ( int i = 0; i < histogram.length; i ++){
    			g.drawLine(i, this.getHeight(), i, this.getHeight() - histogram[i]/displayFactor);
    			histogram[i] = 0;
    				
    		}
    	}
    }
    As you can see the constructor of this jpanel takes the the RGBHistogram as a parameter. and then sets some of its values as its own. I have triple checked with the debugger that RGBHistogram is working as it should and passes the values as it should. Infact with the debugger I was able to verify that

    Java Code:
    this.input = input;
    worked properly and that all the values of bandHistogram were successfully copied to the jpanel's int [] histogram. Now when the jpanel's paint method is called for some reason histogram [] has all its values set to 0. This is causing a /0 exception when I divide by display factor.

    While I checked with the debugger that RGBHistogram works great here is the code for it anyway.

    RGBHistogram
    Java Code:
    import java.awt.Color;
    import java.awt.image.BufferedImage;
    import java.awt.image.Raster;
    
    public class RGBHistogram {
    	
    	private BufferedImage image;
    	private int histogram [] [] = new int [3][257];
    	private int band;
    	private int [] bandHistogram = new int [257];
    	private Color paintColor;
    	
    	public RGBHistogram (BufferedImage image, int band){
    		
    		this.image = image;
    		this.band = band;
    		this.createBandHistogram(image, band);
    		
    	}
    	
    	public void createBandHistogram (BufferedImage image, int band){
    		
    		Raster raster = image.getRaster();
    		int [] tempBandHistogram = new int [257];
    		
    		if (this.band == 0){
    			paintColor = Color.RED;
    			for (int i = 0; i < image.getWidth(); i++){
    				for (int j = 0; j < image.getHeight(); j++){
    				
    					histogram [0][raster.getSample(i,j,0)]++;					
    				}
    			}
    			
    			for (int i = 0; i < 257; i ++){
    				tempBandHistogram[i] = histogram [0][i];
    			}
    			
    			
    		}if (this.band == 1){
    			paintColor = Color.GREEN;
    			for (int i = 0; i < image.getWidth(); i++){
    				for (int j = 0; j < image.getHeight(); j++){
    				
    					histogram [1][raster.getSample(i,j,1)]++;	
    				}
    			}
    			
    			for (int i = 0; i < 257; i ++){
    				tempBandHistogram[i] = histogram [0][i];
    			}
    			
    		}if (this.band == 2){
    			paintColor = Color.BLUE;
    			for (int i = 0; i < image.getWidth(); i++){
    				for (int j = 0; j < image.getHeight(); j++){
    
    					histogram [2][raster.getSample(i,j,2)]++;	
    				}
    			}
    			
    			for (int i = 0; i < 257; i ++){
    				tempBandHistogram[i] = histogram [0][i];
    			}
    		}
    		
    		for ( int i = 0; i < 257; i++){
    			bandHistogram [i] = tempBandHistogram[i];
    		}
    		
    	}
    	
    	public void updateHistogram (BufferedImage image){
    		this.createBandHistogram(image, this.band);
    	}
    	
    	public int [] getBandHistogram(){
    		return bandHistogram;
    	}
    	
    	public Color getBandColor(){
    		return paintColor;
    	}
    
    }
    The jpanels are part of a bigger jframe here are some excerpts from the j frame:

    RBGHistogram and jpanel var declare:
    Java Code:
    	private RGBHistogram rHistogram;
    	private RGBHistogram bHistogram;
    	private RGBHistogram gHistogram;
    
    private HistogramJPanel rHistoPanel;
    	private HistogramJPanel gHistoPanel;
    	private HistogramJPanel bHistoPanel;
    then init for both of them:
    Java Code:
    rHistogram = new RGBHistogram (image,0);
    		gHistogram = new RGBHistogram (image,1);
    		bHistogram = new RGBHistogram (image,2);
    
    rHistoPanel = new HistogramJPanel(rHistogram);
    		rHistoPanel.setBounds(10, 525, 275, 150);
    		contentPane.add(rHistoPanel);
    		
    		gHistoPanel = new HistogramJPanel(gHistogram);
    		gHistoPanel.setBounds(321, 525, 275, 150);
    		contentPane.add(gHistoPanel);
    		
    		bHistoPanel = new HistogramJPanel(bHistogram);
    		bHistoPanel.setBounds(640, 525, 275, 150);
    		contentPane.add(bHistoPanel);
    So basically I dont understand where the values from my input object went between the jpanel's constructor being called and the paint method being called. Any ideas as to what happened or what Im missing?

    Thanks in advance!

  2. #2
    pbrockway2 is online now Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default Re: Interesting problem, variables reset after initialization

    Now when the jpanel's paint method is called for some reason histogram [] has all its values set to 0.
    The reason is that in paintComponent() you say:

    Java Code:
    for ( int i = 0; i < histogram.length; i ++){
        g.drawLine(i, this.getHeight(), i, this.getHeight() - histogram[i]/displayFactor);
        histogram[i] = 0;
                     
    }
    input is giving other classes "direct access" to the array, which, as you've found, can be dangerous.

    If you only want to read values consider giving RGBHistogram a getter method that returns the int value at a particular index.

  3. #3
    aianta is offline Member
    Join Date
    Apr 2011
    Posts
    63
    Rep Power
    0

    Default Re: Interesting problem, variables reset after initialization

    Quote Originally Posted by pbrockway2 View Post
    The reason is that in paintComponent() you say:

    Java Code:
    for ( int i = 0; i < histogram.length; i ++){
        g.drawLine(i, this.getHeight(), i, this.getHeight() - histogram[i]/displayFactor);
        histogram[i] = 0;
                     
    }
    input is giving other classes "direct access" to the array, which, as you've found, can be dangerous.

    If you only want to read values consider giving RGBHistogram a getter method that returns the int value at a particular index.

    Ok So I made this method in RGB histogram:
    Java Code:
    	public int getBandHistogram(int index){
    		return bandHistogram[index];
    	}
    and for test purposes created this for the jpanel Im still getting an /by zero arithmetic error on the like marked.

    Java Code:
    protected void paintComponent(Graphics g){
    		super.paintComponent(g);
    		
    		int max = 0;
    	
    		for (int i = 0; i < input.getBandHistogram().length; i++){
    			if (max < input.getBandHistogram(i))
    				max = input.getBandHistogram(i);
    		}
    		
    		displayFactor = max/150;
    	
    		g.setColor(paintColor);
    			
    		for ( int i = 0; i < input.getBandHistogram().length; i ++){
    			g.drawLine(i, this.getHeight(), i, this.getHeight() - input.getBandHistogram(i)/displayFactor); ***********ERROR***********
    		//	histogram[i] = 0;
    				
    		}
    	}
    Here is the code of the actual error

    Java Code:
    Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException: / by zero
    	at com.zgentech.VideoAnalysisExperiment.HistogramJPanel.paintComponent(HistogramJPanel.java:36)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JLayeredPane.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
    	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
    	at javax.swing.RepaintManager.paint(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
    	at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
    	at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
    	at java.awt.Container.paint(Unknown Source)
    	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
    	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
    	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    	at java.awt.EventQueue.dispatchEvent(Unknown Source)
    	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.run(Unknown Source)
    what did I do wrong? Thanks in advance.

  4. #4
    pbrockway2 is online now Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default Re: Interesting problem, variables reset after initialization

    Java Code:
    g.drawLine(i, this.getHeight(), i, this.getHeight() - input.getBandHistogram(i)/displayFactor);
    The problem here is that displayFactor is zero. If that's not clear from the error message you can test it with:

    Java Code:
    displayFactor = max/150;
    System.out.println("Setting displayFactor to " + displayFactor);
         
    g.setColor(paintColor);
                 
    for ( int i = 0; i < input.getBandHistogram().length; i ++){
        g.drawLine(// etc
        
        //  histogram[i] = 0;
    }
    Remember that when you do integer division like "max/150" the result is truncated (rounded down). Evidently max <= 150 and you are getting a result of zero. This is true however you declare dispayFactor - even a double will end up being zero.

    In fact you declare dispayFactor as an int. From the way you use it you might want to consider making it a double. And saying

    Java Code:
    displayFactor = (double)max/150;
    System.out.println("Setting displayFactor to " + displayFactor);
    The "cast" of max to double will ensure that the fractional part (which is the important part of the result) is not discarded.

    There will probably need to be a cast back to int again when you draw the line (as drawLine() expects an int argument).

  5. #5
    aianta is offline Member
    Join Date
    Apr 2011
    Posts
    63
    Rep Power
    0

    Default Re: Interesting problem, variables reset after initialization

    I am well aware of where the issue is, however display factor is not the root cause of the problem. Display factor is generated by looking at the maximums from the input.getbandHistogram(x) (this array should be full of a bunch of numbers, and it is when I initialize the jpanel).

    Using debugger:

    values of bandHistgram at initialization of the jpanel

    Java Code:
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 8, 7, 22, 125, 
    65, 708, 300, 155, 128, 133, 202, 220, 231, 273, 381, 357, 202, 178, 222, 208, 257, 206, 254, 244, 263, 306, 274, 332, 350, 365, 
    377, 392, 416, 482, 503, 535, 519, 625, 756, 749, 750, 720, 636, 562, 581, 607, 602, 616, 565, 506, 443, 548, 722, 1380, 1679, 1877, 2047, 1694, 1487, 1264, 991, 744, 725, 661, 735, 826, 880, 928, 1021, 1171, 1290,
     1398, 1355, 1034, 961, 896, 824, 817, 912, 1040, 1043, 1301, 1156, 820, 892, 755, 626, 600, 606, 558, 634, 582, 556
    , 501, 360, 390, 406, 397, 394, 338, 311, 252, 248, 273, 321, 318, 268, 265, 256, 310, 319, 317, 276, 230, 183, 187, 184, 169, 151, 144, 191, 165, 188, 208, 205, 236,
     243, 234, 209, 250, 229, 257, 257, 268, 275, 289, 312, 304, 298, 321, 296, 278, 234, 251, 275, 234, 205, 192, 200, 208, 221, 209, 210, 169, 207, 210, 191, 208, 213, 167, 205, 196, 168, 162, 172, 156, 162, 175, 161, 151, 127, 123, 134, 111, 111, 139, 99, 107, 110, 117, 112, 109, 113, 137, 109, 125, 126, 116, 115, 157, 223, 312, 459, 656, 813, 859, 853, 490, 373, 233, 206, 157, 126, 115, 93, 90, 82, 83, 85, 78, 68, 80, 78, 88, 97, 87, 95, 86, 90, 76, 68, 66, 64, 54, 43, 31, 22, 18, 21, 8, 16, 10, 5, 3, 7, 4, 4, 10, 14, 15, 15, 21, 26, 74, 0]
    As you can see the display factor should clearly not be zero or anything close really, since all im doing is getting the biggest number from that array and dividing it by 150.

    Now going back to the debuger, I notice that the band histogram is whipped clean (all set to zeros) by the time the paint method is called, this is what baffles me. What is causing the list above to be rewritten to 0,0,0,0....etc. between the initialization of the jpanel and the call to the paint method.

    That is what I really need help with.

  6. #6
    pbrockway2 is online now Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default Re: Interesting problem, variables reset after initialization

    OK, so you have code somewhere that is assigning zero to the elements of the array.

    Obviously the RGBHistogram class is one place to look. createBandHistogram() is one place the assignment might happen. So dump the values of the array when that method has been called (or use the debugger). Both the createBandHistogram() and the updateHistogram() are public, so it might be a good idea to add code in the callers of these methods - just before the call - so that you can later tell what was going on when the assignment takes place. (Or rely on the debugger for this.)

    bandHistogram is private which suggests createBandHistogram() is the *only* place the assignment could take place. (So long as the public method returning the array was removed.)

  7. #7
    aianta is offline Member
    Join Date
    Apr 2011
    Posts
    63
    Rep Power
    0

    Default Re: Interesting problem, variables reset after initialization

    Quote Originally Posted by pbrockway2 View Post
    OK, so you have code somewhere that is assigning zero to the elements of the array.

    Obviously the RGBHistogram class is one place to look. createBandHistogram() is one place the assignment might happen. So dump the values of the array when that method has been called (or use the debugger). Both the createBandHistogram() and the updateHistogram() are public, so it might be a good idea to add code in the callers of these methods - just before the call - so that you can later tell what was going on when the assignment takes place. (Or rely on the debugger for this.)

    bandHistogram is private which suggests createBandHistogram() is the *only* place the assignment could take place. (So long as the public method returning the array was removed.)

    Well I have narrowed it down to the line that has to be causing the trouble, but I don't understand why it is causing the trouble.

    The only line in createBandHistogram that could change the histogram to 0s is this one:
    Java Code:
    int [] tempBandHistogram = new int [257];
    here is the newest compleate code to RGBHistogram

    Java Code:
    import java.awt.Color;
    import java.awt.image.BufferedImage;
    import java.awt.image.Raster;
    
    public class RGBHistogram {
    	
    	private BufferedImage image;
    	private int histogram [] [] = new int [3][257];
    	private int band;
    	private int [] bandHistogram = new int [257];
    	private Color paintColor;
    	
    	public RGBHistogram (BufferedImage image, int band){
    		
    		this.image = image;
    		this.band = band;
    		this.createBandHistogram(image, band);
    		
    	}
    	
    	public void createBandHistogram (BufferedImage image, int band){
    		
    		Raster raster = image.getRaster();
    		int [] tempBandHistogram = new int [257];
    		
    		if (this.band == 0){
    			paintColor = Color.RED;
    			for (int i = 0; i < image.getWidth(); i++){
    				for (int j = 0; j < image.getHeight(); j++){
    				
    					histogram [0][raster.getSample(i,j,0)]++;					
    				}
    			}
    			
    			for (int i = 0; i < 257; i ++){
    				tempBandHistogram[i] = histogram [0][i];
    			}
    			
    			
    		}if (this.band == 1){
    			paintColor = Color.GREEN;
    			for (int i = 0; i < image.getWidth(); i++){
    				for (int j = 0; j < image.getHeight(); j++){
    				
    					histogram [1][raster.getSample(i,j,1)]++;	
    				}
    			}
    			
    			for (int i = 0; i < 257; i ++){
    				tempBandHistogram[i] = histogram [0][i];
    			}
    			
    		}if (this.band == 2){
    			paintColor = Color.BLUE;
    			for (int i = 0; i < image.getWidth(); i++){
    				for (int j = 0; j < image.getHeight(); j++){
    
    					histogram [2][raster.getSample(i,j,2)]++;	
    				}
    			}
    			
    			for (int i = 0; i < 257; i ++){
    				tempBandHistogram[i] = histogram [0][i];
    			}
    		}
    
    		
    		for ( int i = 0; i < 257; i++){
    			bandHistogram [i] = tempBandHistogram[i];
    		}
    		
    	}
    	
    	public void updateHistogram (BufferedImage image){
    		this.createBandHistogram(image, this.band);
    	}
    	
    	
    	public int getBandHistogram(int index){
    		return bandHistogram[index];
    	}
    	
    	public Color getBandColor(){
    		return paintColor;
    	}
    
    }
    I wrote that line so that whenever createBandHistogram would be called, it would create a clean new array, but I don't see how its being called and passed to the jpanel without any values. Especially when the method works fine when its result is passed to the jpanels constructor but fails in the paint method
    Last edited by aianta; 11-02-2012 at 01:13 AM.

  8. #8
    pbrockway2 is online now Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default Re: Interesting problem, variables reset after initialization

    Sorry for the late post.

    So work backwards and figure out what the value of band was when bandHistogram was assigned the zeros.

    When band is 1 (or 2), you assign values to histogram[1][...] (histogram[2][...]) but you use the values in histogram[0][...] to assign values to tempBandHistogram and bandHistogram, which doesn't seem right.

  9. #9
    aianta is offline Member
    Join Date
    Apr 2011
    Posts
    63
    Rep Power
    0

    Default Re: Interesting problem, variables reset after initialization

    Quote Originally Posted by pbrockway2 View Post
    Sorry for the late post.

    So work backwards and figure out what the value of band was when bandHistogram was assigned the zeros.

    When band is 1 (or 2), you assign values to histogram[1][...] (histogram[2][...]) but you use the values in histogram[0][...] to assign values to tempBandHistogram and bandHistogram, which doesn't seem right.
    Sorry for my late post too. Thanks, that was the issue, I was always taking the values from histogram [0]. Once again thanks for you time and patience :)

  10. #10
    pbrockway2 is online now Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default Re: Interesting problem, variables reset after initialization

    Great, I'm glad you've got it sorted out!

    If you removed the redundant code duplication (and the magic 0/1/2) the problem would never have occured. Something along the lines of:

    Java Code:
    private final Color[] pcArr = {Color.RED, Color.GREEN, Color.BLUE};
    
    // ...
    
    public void createBandHistogram (BufferedImage image, int band){
             
        Raster raster = image.getRaster();
        int [] tempBandHistogram = new int [257];
             
        paintColor = pcArr[band];
        for (int i = 0; i < image.getWidth(); i++){
            for (int j = 0; j < image.getHeight(); j++){
                histogram [band][raster.getSample(i,j,band)]++;                   
            }
        }
                 
        for (int i = 0; i < 257; i ++){
            tempBandHistogram[i] = histogram [band][i];
        }
             
        for ( int i = 0; i < 257; i++){
            bandHistogram [i] = tempBandHistogram[i];
        }
    }
    This code, in turn, suggests a further improvement: to remove tempBandHistogram which isn't doing a lot.

  11. #11
    aianta is offline Member
    Join Date
    Apr 2011
    Posts
    63
    Rep Power
    0

    Default Re: Interesting problem, variables reset after initialization

    Quote Originally Posted by pbrockway2 View Post
    Great, I'm glad you've got it sorted out!

    If you removed the redundant code duplication (and the magic 0/1/2) the problem would never have occured. Something along the lines of:

    Java Code:
    private final Color[] pcArr = {Color.RED, Color.GREEN, Color.BLUE};
    
    // ...
    
    public void createBandHistogram (BufferedImage image, int band){
             
        Raster raster = image.getRaster();
        int [] tempBandHistogram = new int [257];
             
        paintColor = pcArr[band];
        for (int i = 0; i < image.getWidth(); i++){
            for (int j = 0; j < image.getHeight(); j++){
                histogram [band][raster.getSample(i,j,band)]++;                   
            }
        }
                 
        for (int i = 0; i < 257; i ++){
            tempBandHistogram[i] = histogram [band][i];
        }
             
        for ( int i = 0; i < 257; i++){
            bandHistogram [i] = tempBandHistogram[i];
        }
    }
    This code, in turn, suggests a further improvement: to remove tempBandHistogram which isn't doing a lot.
    I made those changes, and I guess while we are kind of on the topic, are there any tricks for spotting some design issues like this. I assume that as I program more Ill get more of a feel for when Im making these design mistakes but is there any other advice that you can give me?

  12. #12
    pbrockway2 is online now Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,574
    Rep Power
    12

    Default Re: Interesting problem, variables reset after initialization

    are there any tricks for spotting some design issues like this
    This was a nice problem - and illustrated a couple of things. I can't see any others (but others here might).

    To repeat though, because they are good practices. (I'm no expert with code of any complexity. I just have rules of thumb.)

    (1) Make methods and variables private. And be very cautious about passing *arrays* to callers of the class's methods. When something goes wrong with the state of an instance of the class (eg an array suddenly appears filled with zeros) you are obliged to check every line of code that could possibly have got its hands on the data. It is *much* nicer when state changing code is concentrated in the class itself: one place to check.

    (So - as an aside - I would ask myself whether I really need createBandHistogram() to be public. If it is intended to always be called via updateHistgram() then it should be private.)

    (2) Don't repeat code. The three if-else blocks corresponding to the different bands were all so similar that they could all be merged into one (as shown). If there is less code there will be fewer places for bugs! Here the bug was that the array index had to be kept "in synch" with the band being used. And repeating the code resulted in a cut-n-paste bug.

Similar Threads

  1. instance variables initialization
    By ghostrider in forum New To Java
    Replies: 6
    Last Post: 08-27-2012, 08:00 AM
  2. Clear/Reset Button Problem
    By Ryan10 in forum New To Java
    Replies: 10
    Last Post: 04-12-2011, 04:04 PM
  3. Interesting CS problem. Need help.
    By xtrmi in forum New To Java
    Replies: 1
    Last Post: 05-02-2009, 04:51 AM
  4. Tricky but very interesting problem
    By ravjot28 in forum New To Java
    Replies: 4
    Last Post: 06-26-2008, 02:43 PM
  5. in struts reset was problem
    By sureshBabu in forum Web Frameworks
    Replies: 1
    Last Post: 05-07-2008, 04:26 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •