Search code examples
javanetbeanswindows-8.1joptionpaneimageicon

How to clear an image from memory when repeating an operation in Java?


I'm struggling with a new program.

The program is designed to obtain a spectrum from a webcam and compare it with a reference spectrum. This is done when the use clicks a button called 'captureButton'.

At the end of the operation, the program displays a plot of the spectrum (created externally via a batch file through Scilab) in a message dialogue. This all happens perfectly and as expected. However, if the operation is run again (by pressing the button again) the process takes place fine, but the image displayed in the message dialogue is the old image from the previous run.

This happens despite the fact that at the beginning of the operation, all old files are erased and then recreated using the new data.

I suspect then that the old image is somehow being stored in the memory, rather than being recalled from the new file the second time around.

I've tried requesting the garbage collector, to no effect.

Here is the code (I've removed irrelevant segments as this is a fairly long code)...

//Imports etc here

public class VSAWindow extends javax.swing.JFrame {

    public VSAWindow() {
        initComponents();
        //Set defaults for user input
        sampleText.setText("50");
        toleranceText.setText("1");
        acceptanceText.setText("10");

        //Clear Calibration window and set calibration spectrum image
        jLabel10.setText("");
        jLabel11.setText("");
        ImageIcon icon = new ImageIcon("reference/mainspectrum.png");
        jLabel10.setIcon(icon);
    }


        @SuppressWarnings("unchecked")
        // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
        private void initComponents() {

        captureButton = new javax.swing.JButton();
        // Some other declarations...
        jButton1 = new javax.swing.JButton();
        calibrateButton = new javax.swing.JButton();
        jLabel10 = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        captureButton.setText("Capture");
        captureButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                captureButtonActionPerformed(evt);
            }
        });

    //Some code which sets a load of text on screen...

        jButton1.setText("EXIT");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
    jLabel10.setText("jLabel10");

    jLabel11.setText("jLabel11");

    //A load of code added by the IDE for adding various components      

private void captureButtonActionPerformed(java.awt.event.ActionEvent evt) {                                              
    //CLEAR ALL PREVIOUS IF POSSIBLE
    System.gc();

    //Check user input values for validity
    try {
        String smpIn = sampleText.getText();
        String tolIn = toleranceText.getText();
        String accIn = acceptanceText.getText();

        int smpVl = Integer.parseInt(smpIn);
        double tolVl = Integer.parseInt(tolIn);
        int accVl = Integer.parseInt(accIn);
        int stopgo = 0; //Condition variable to prevent invalid operation

        if (smpVl >= 0 && smpVl <= 766 && tolVl >= 0 && tolVl <= 100 && accVl >= 0 && accVl <= 100) {
            stopgo = 1;
        }

        if (stopgo == 1) {//Proceed if input values have been checked for validity
            try {
                //BEFORE BEGINNING CLEAR ALL FILES FROM PREVIOUS RUNS
                //This will prevent old data from being displayed in
                //the event of system slowdown
                File del1 = new File("convert.bat");
                File del2 = new File("inplot.png");
                File del3 = new File("newdata.csv");
                File del4 = new File("peakdata.csv");
                File del5 = new File("peaks.sce");
                File del6 = new File("refbat.bat");
                File del7 = new File("refplot.png");
                File del8 = new File("rgb.sce");
                File del9 = new File("rgbbat.bat");
                File del10 = new File("test.png");
                File del11 = new File("spectra\\newspectrum.ppm");
                File del12 = new File("spectra\\convspectrum.doc");

                del1.delete();
                del2.delete();
                del3.delete();
                del4.delete();
                del5.delete();
                del6.delete();
                del7.delete();
                del8.delete();
                del9.delete();
                del10.delete();
                del11.delete();
                del12.delete();

                //CAPTURE SPECTRUM IMAGE
                Webcam webcam = Webcam.getDefault();
                Dimension size = new Dimension(640, 480);
                webcam.setViewSize(size);
                webcam.open();
                BufferedImage image = webcam.getImage();
                try {
                    ImageIO.write(image, "PNG", new File("test.png"));
                } catch (IOException ex) {
                    Logger.getLogger(VSAWindow.class.getName()).log(Level.SEVERE, null, ex);
                }
                System.out.println("Obtaining data from spectrometer...");

                //CREATE BATCH FILE FOR IMAGE CONVERSION TO .PPM FORMAT
                String filename = "convert.bat";
                WriteFile data = new WriteFile(filename, false);
                WriteFile dataline = new WriteFile(filename, true);
                data.WriteToFile("cd \"C:\\Program Files (x86)\\IrfanView\"");
                dataline.WriteToFile("i_view32.exe C:\\Users\\Guy\\Documents\\NetBeansProjects\\VSpecAnalyser\\test.png /convert=C:\\Users\\Guy\\Documents\\NetBeansProjects\\VSpecAnalyser\\spectra\\newspectrum.ppm");
                dataline.WriteToFile("exit");

                //Wait for processes to finish...
                File f = new File("test.png");
                int msgCheck = 0;//Variable to prevent repeated i/o
                while (!f.exists()) {
                    if (msgCheck == 0) {
                        System.out.println("Building spectral data...");
                    }
                    msgCheck = 1;
                }
                //Shuts webcam and proceeds as long as input has been obtained
                webcam.close();
                //EXECUTE CONVERSION BATCH FILE
                Runtime.getRuntime().exec("cmd /c start convert.bat");

                //CONVERSION BY TO LINE BY LINE FORMAT - NEEDS STREAMLINING SOMEHOW
                //Wait for file to be created:
                File fn = new File("spectra\\newspectrum.ppm");
                int msgCheck2 = 0;//Variable to prevent repeated i/o
                while (!fn.exists()) {
                    if (msgCheck2 == 0) {
                        System.out.println("Performing file operations....");
                    }
                    msgCheck2 = 1;
                }//Proceeds once file has been converted and placed in 'spectra' folder

                //Open file for format conversion
                ReadFile open = new ReadFile("C:\\Users\\Guy\\Documents\\NetBeansProjects\\VSpecAnalyser\\spectra\\newspectrum.ppm");
                String[] readLines;

                readLines = open.OpenFile();

                //Prepare Writefile
                WriteFile begin = new WriteFile("C:\\Users\\Guy\\Documents\\NetBeansProjects\\VSpecAnalyser\\spectra\\convspectrum.doc", false);
                begin.WriteToFile("");

                //Create file append code
                WriteFile write = new WriteFile("C:\\Users\\Guy\\Documents\\NetBeansProjects\\VSpecAnalyser\\spectra\\convspectrum.doc", true);

                //Begin looping and adding to new file
                String columns = readLines[2].split("\\ ")[0];
                int nos = Integer.parseInt(columns);
                for (int i = 0; i < readLines.length; i++) {

                    if (i < 4) {
                        write.WriteToFile(readLines[i]);
                    } else if (i == 2) {

                        //Splits condensed data and rebuilds as line-by-line format
                    } else if (i >= 4 && i < nos) {
                        String[] lnMk = readLines[i].split("[\\W]");
                        for (int j = 0; j < lnMk.length; j++) {
                            write.WriteToFile(lnMk[j]);
                        }
                    }
                }

                //BEGIN DATA ANALYSIS
                //FILE READING PROCEDURE
                ReadFile file = new ReadFile("spectra/convspectrum.doc");//Read in filename to be opened
                String aryLines[];//Declare string array for file contents in line by line read
                aryLines = file.OpenFile();//Read file line by line and assign each line to a sequential array index

                //DECLARE VARIABLES
                String beforeSpc = aryLines[3].split("\\ ")[0];
                System.out.println("Number of columns = " + beforeSpc);
                int docWidth = Integer.parseInt(beforeSpc);//Gets spectrum width from file header
                int rgbCount = 0;//Index for counting final RGB indices
                int sample = smpVl;//Declares lower limit for sampling (Sample = r+g+b)(min=0, max = 765)
                String[] rgbArray = new String[aryLines.length];//Declare array for storage of final RGB values

                //CREATE CSV FILE FOR SCILAB - INPUT SPECTRUM
                WriteFile newData = new WriteFile("newdata.csv", false);
                newData.WriteToFile("");

                //CREATE SCILAB SCRIPT FILE - INPUT SPECTRUM
                WriteFile createSciRGB = new WriteFile("rgb.sce", false);
                createSciRGB.WriteToFile("");

                //CONFIGURE SCILAB SCRIPT FOR RGB DATA - INPUT SPECTRUM
                WriteFile addSciRGB = new WriteFile("rgb.sce", true);
                addSciRGB.WriteToFile("cd(\"C:\\Users\\Guy\\Documents\\NetBeansProjects\\VSpecAnalyser\");");
                addSciRGB.WriteToFile("y = evstr(read_csv(\"newdata.csv\"));");
                addSciRGB.WriteToFile("xlabel(\"Wavelength (nm)\")");
                addSciRGB.WriteToFile("ylabel(\"Intesity (Combined RGB Value)\")");
                addSciRGB.WriteToFile("plot2d(y)");
                addSciRGB.WriteToFile("xs2png(0, \"inplot.png\" )");
                addSciRGB.WriteToFile("exit");

                //CREATE BATCH FILE FOR RUNNING SCILAB (RGB INPUT SPECTRUM)
                WriteFile rgbBat = new WriteFile("rgbbat.bat", false);
                rgbBat.WriteToFile("\"C:/Program Files/scilab-5.5.0/bin/Scilex.exe\" scilab-adv-cli -f \"rgb.sce\" -nw");
                WriteFile addRgbBat = new WriteFile("rgbbat.bat", true);
                addRgbBat.WriteToFile("exit");

                //BEGIN LOOPING THROUGH INPUT FILE
                for (int i = 0; i < 3 * docWidth; i++) {//Restricts loop to single line by stopping after 1x width of sample spectrum
                    //System.out.println(aryLines[i]);
                    if (i >= 6 && i % 3 == 0) {

                        //ASSIGN R,G,B VALUES
                        int r = Integer.parseInt(aryLines[i - 2]);
                        int g = Integer.parseInt(aryLines[i - 1]);
                        int b = Integer.parseInt(aryLines[i]);
                        int dataR = Integer.parseInt(aryLines[i - 2]);
                        int dataG = Integer.parseInt(aryLines[i - 1]);
                        int dataB = Integer.parseInt(aryLines[i]);
                        int lineSpec = dataR + dataG + dataB;
                        String dataPoint = Integer.toString(lineSpec);

                        //ADD RGB DATA TO SCILAB FILE - INPUT SPECTRUM
                        WriteFile peaks = new WriteFile("newdata.csv", true);
                        peaks.WriteToFile(dataPoint);

                        int pixSum = r + g + b;//Creates measure of pixel significance
                        if (pixSum > sample) {
                            rgbArray[rgbCount] = aryLines[i - 2] + " " + aryLines[i - 1] + " " + aryLines[i];
                            rgbCount++;
                        }
                    }
                }
                //OUTPUT ARRAY OF FINAL RGB VALUES
                for (int j = 0; j < rgbArray.length; j++) {
                    if (rgbArray[j] != null) {
                        System.out.println(rgbArray[j]);
                    }
                }
        //END COLLECTION OF INPUT DATA

                //BEGIN CREATION OF COMPARISON DATA
                //FILE READING PROCEDURE FOR REFERENCE SPECTRUM
                ReadFile specFile = new ReadFile("reference/mainspectrum.ppm");//Read in filename to be opened
                String specLines[];//Declare string array for file contents in line by line read
                specLines = specFile.OpenFile();//Read file line by line and assign each line to a sequential array index

                //DECLARE VARIABLES
                String specBeforeSpc = specLines[2].split("\\ ")[0];//Gets spectrum width from file header
                System.out.println("Number of columns = " + specBeforeSpc);
                int specWidth = Integer.parseInt(specBeforeSpc);
                int specCount = 0;//Index for counting reference RGB indices
                String[] specArray = new String[specWidth];//Declare array for storage of reference RGB values

                //CREATE CSV FILE FOR SCILAB - REFERENCE SPECTRUM
                WriteFile stFile = new WriteFile("peakdata.csv", false);//Creates and clears file for line spectrum data
                stFile.WriteToFile("");

                //CREATE SCILAB SCRIPT FILE - REFERENCE SPECTRUM
                WriteFile createSciSpec = new WriteFile("peaks.sce", false);
                createSciSpec.WriteToFile("");

                //CONFIGURE SCILAB SCRIPT FOR RGB DATA - REFERENCE SPECTRUM
                WriteFile addSciSpec = new WriteFile("peaks.sce", true);
                addSciSpec.WriteToFile("cd(\"C:\\Users\\Guy\\Documents\\NetBeansProjects\\VSpecAnalyser\");");
                addSciSpec.WriteToFile("y = evstr(read_csv(\"peakdata.csv\"));");
                addSciSpec.WriteToFile("xlabel(\"Wavelength (nm)\")");
                addSciSpec.WriteToFile("ylabel(\"Intesity (Combined RGB Value)\")");
                addSciSpec.WriteToFile("plot2d(y)");
                addSciSpec.WriteToFile("xs2png(0, \"refplot.png\" )");
                addSciSpec.WriteToFile("exit");

                //CREATE BATCH FILE FOR RUNNING SCILAB (REFERENCE SPECTRUM)
                WriteFile refBat = new WriteFile("refbat.bat", false);
                refBat.WriteToFile("\"C:/Program Files/scilab-5.5.0/bin/Scilex.exe\" scilab-adv-cli -f \"peaks.sce\" -nw");
                WriteFile addRefBat = new WriteFile("refbat.bat", true);
                addRefBat.WriteToFile("exit");

                //BEGIN LOOPING THROUGH SPECTRUM REFERENCE FILE
                for (int i = 0; i < 3 * specWidth; i++) {//Restricts loop to single line by stopping after 1x width of reference spectrum

                    //Eliminate header and compress RGB lines into single, 3 point entries
                    if (i >= 6 && i % 3 == 0) {

                        //ASSIGN R,G,B VALUES TO REFERENCE SPECTRUM ARRAY
                        specArray[specCount] = specLines[i - 2] + " " + specLines[i - 1] + " " + specLines[i];
                        specCount++;
                        int dataR = Integer.parseInt(specLines[i - 2]);
                        int dataG = Integer.parseInt(specLines[i - 1]);
                        int dataB = Integer.parseInt(specLines[i]);
                        int lineSpec = dataR + dataG + dataB;
                        String dataPoint = Integer.toString(lineSpec);

                        //ADD DATA TO SCILAB FILE - REFERENCE SPECTRUM
                        WriteFile peaks = new WriteFile("peakdata.csv", true);
                        peaks.WriteToFile(dataPoint);
                    }
                }
                System.out.println("Reference Spectrum Obtained");

                //COMPARE INPUT AND REFERENCE SPECTRA
                //Set matching tolerance:
                double tol = (765 / 100) * tolVl;

                //Set lower threshold for partial matches
                int disp = 100 - accVl;

                //Find length of input RGB input array to prevent null pointers
                int rgbLength = 0;

                //Declare null variables for match counts
                int matchCount = 0;
                int perfCount = 0;
                int possCount = 0;

                //Determine length of RGB Input data array
                for (int x = 0; x < rgbArray.length; x++) {
                    if (rgbArray[x] != null) {
                        rgbLength++;
                    }
                }

                //BEGIN COMPARISON
                //Check each input RGB value...
                for (int l = 0; l < rgbLength; l++) {
                    String[] colours = rgbArray[l].split(" ");
                    String sred = colours[0];
                    String sgreen = colours[1];
                    String sblue = colours[2];
                    int red = Integer.parseInt(sred);
                    int green = Integer.parseInt(sgreen);
                    int blue = Integer.parseInt(sblue);

                    //...against each reference value
                    for (int m = 0; m < specArray.length - 2; m++) {
                        String[] cols = specArray[m].split(" ");
                        String sr = cols[0];
                        String sg = cols[1];
                        String sb = cols[2];
                        int r = Integer.parseInt(sr);
                        int g = Integer.parseInt(sg);
                        int b = Integer.parseInt(sb);
                        double wavelength = 380 + m / 3;

                        //Identify perfect matches
                        if (red == r && green == g && blue == b) {
                            perfCount++;
                            matchCount++;
                            System.out.println("PERFECT MATCH! Found at " + m + " of reference and " + l + " of input");
                           //Some code to output results

                            //Identify imperfect matches based on tolerance
                        } else if (red - r < tol && green - g < tol && blue - b < tol && red - r > -tol && green - g > -tol && blue - b > -tol) {

                            //Calculate possible matches regardless of parameters
                            possCount++;

                            //CALCULATE MATCH QUALITY
                            //Initialise variables
                            double rperc = 100;
                            double gperc = 100;
                            double bperc = 100;
                            double tperc = 100;

                            //Provide conditions
                            if (red > r) {
                                rperc = (100 / (double) red) * (double) r;
                            } else if (red < r) {
                                rperc = (100 / (double) r) * (double) red;
                            }
                            if (green > g) {
                                gperc = (100 / (double) green) * (double) g;
                            } else if (green < g) {
                                gperc = (100 / (double) g) * (double) green;
                            }
                            if (blue > b) {
                                bperc = (100 / (double) blue) * (double) b;
                            } else if (blue < b) {
                                bperc = (100 / (double) b) * (double) blue;
                            }

                            //Small discrepancies involving zero values are automatically given a 95% quality rating
                            if (r == 0 || red == 0) {
                                rperc = 95;
                            }
                            if (g == 0 || green == 0) {
                                gperc = 95;
                            }
                            if (b == 0 || blue == 0) {
                                bperc = 95;
                            }
                            if (red == r) {
                                rperc = 100;
                            }
                            if (green == g) {
                                gperc = 100;
                            }
                            if (blue == b) {
                                bperc = 100;
                            }
                            double tot = (tperc / 300) * (rperc + gperc + bperc);

                            //Check whether available matches are within specified range
                            if (tot > disp) {
                                matchCount++;

                                //Display Match parameters
                                System.out.println("Partial MATCH! Found at " + m + " of reference and " + l + " of input");
                                //Some more code to output results

                                //Calculate and display final quality value and breakdown
                                System.out.println("Match Quality: " + tot + "% (R: " + rperc + " G: " + gperc + " B: " + bperc);
                            }
                        }
                    }

                }
                //More results

                //CHECK THAT BATCH FILES FOR PLOTTING EXIST
                File chkrgb = new File("rgbbat.bat");
                File chkref = new File("refbat.bat");

                while (!chkrgb.exists()) {
                    //Do nothing, just wait
                }
                while (!chkref.exists()) {
                    //Do nothing, just wait
                }

                //PRODUCE SCILAB PLOTS FOR BOTH REFERENCE AND INPUT SPECTRA
                Runtime.getRuntime().exec("cmd /c start refbat.bat");
                Runtime.getRuntime().exec("cmd /c start rgbbat.bat");

                //CHECK PNG PLOTS HAVE BEEN GENERATED
                File chkrgbpng = new File("inplot.png");
                File chkrefpng = new File("refplot.png");

                while (!chkrgbpng.exists()) {
                    System.out.println("Loading RGB Plot...");
                    Thread.sleep(2000);
                }
                while (!chkrefpng.exists()) {
                    System.out.println("Loading Reference Plot...");
                    Thread.sleep(2000);
                }

                //PLACE RGB PLOT IN WINDOW
                System.out.println("Setting plot to screen...");
                ImageIcon icon2 = new ImageIcon("inplot.png");
                String msgTitle = "";
                String msgCaption = "Wavelength in nm";
                JOptionPane.showMessageDialog(null, msgCaption, msgTitle, JOptionPane.INFORMATION_MESSAGE, icon2);

            } catch (IOException ex) {
                Logger.getLogger(VSAWindow.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            JOptionPane.showMessageDialog(null, "Please select valid input values!");
        }
    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, e);
    }
}                                             

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    System.exit(0);
}                                        

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {

    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(VSAWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(VSAWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(VSAWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(VSAWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new VSAWindow().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     

// End of variables declaration                   
}

The Image in question is 'icon2', near the end of the code, beneath the comment "//PLACE RGB PLOT IN WINDOW", i.e:

                System.out.println("Setting plot to screen...");
                ImageIcon icon2 = new ImageIcon("inplot.png");
                String msgTitle = "";
                String msgCaption = "Wavelength in nm";
                JOptionPane.showMessageDialog(null, msgCaption, msgTitle, JOptionPane.INFORMATION_MESSAGE, icon2);

I'm working in Netbeans 8 on Windows 8.1.

Why is the system remembering the image from the previous run, and how can I stop this?

Many thanks, and apologies for the length of the code, I didn't want to leave anything out that might be causing this issue. If I can improve the question in any way, please let me know so that I can prevent myself from being blocked!


Solution

  • The preferred solution would be to use ImageIO.read over ImageIcon(String), but if you have to, you should call icon2.flush() before attempting to reload it.

    See Image#flush and Reading/Loading Images for more details