Background info: I’ve made a program that uploads an image using JFileChooser and fills in the space of the JFrame. I then apply filters via buttons. Currently 3 of my 4 filters work, or all except my mirror one. It randomly (or I guess not so randomly as there’s always a reason, I just don’t know what I did) worked a couple times.
My Question: I’ve attempted following a tutorial but had to make slight changes so that I can save it to a new file via a button that has a JFile Chooser. Currently when I save it, it does not mirror however my other filters do what there supposed to with the same slight changes. What is wrong with my mirror logic? Any help is appreciated!
My code:
Global Variables:
// Save Button private final JButton saveButton = new JButton("Save Files"); private File selFile1; private File output = new File("Output.png"); private File selFile2; private String path1;
Upload file:
// Browse Files Button ActionListener BrowseButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser getFile = new JFileChooser(); getFile.setCurrentDirectory(new File(System.getProperty("user.home"))); // Filter files FileNameExtensionFilter filter1 = new FileNameExtensionFilter("*.Images", "jpg", "png"); getFile.addChoosableFileFilter(filter1); int res = getFile.showSaveDialog(null); if(res == JFileChooser.APPROVE_OPTION) { selFile1 = getFile.getSelectedFile(); path1 = selFile1.getAbsolutePath(); label.setIcon(resize(path1)); System.out.println("1st selFile1 = " + selFile1); try { getImg = ImageIO.read(selFile1); } catch (IOException ex) { System.out.println(ex); } // End try-catch } // End if } // End actionPerformer }); // End ActionListener }); // End ActionListener
Save File:
// Save Files Button ActionListener saveButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser getFile = new JFileChooser(); getFile.setCurrentDirectory(new File(System.getProperty("user.home"))); // Filter files FileNameExtensionFilter filter1 = new FileNameExtensionFilter("*.Images", "jpg", "png"); getFile.addChoosableFileFilter(filter1); int res = getFile.showSaveDialog(null); if(res == JFileChooser.APPROVE_OPTION) { selFile2 = getFile.getSelectedFile(); path1 = selFile2.getAbsolutePath(); label.setIcon(resize(path1)); System.out.println("1st selFile1 = " + selFile2); try { ImageIO.write(getImg, "png", selFile2); } catch (IOException ex) { System.out.println(ex); } // End try-catch } // End if } // End actionPerformer }); // End ActionListener
grayScale method that works:
grayScale.setMnemonic('G'); //Hot key // ActionListener for grayscale button grayScale.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { File f = selFile1; // Read image try{ getImg = ImageIO.read(f); } catch(IOException ef){ System.out.println(ef); } // End try-catch // Get image width and height int width = getImg.getWidth(); int height = getImg.getHeight(); // Convert to grayscale for(int y = 0; y < height; y++){ for(int x = 0; x < width; x++){ int p = getImg.getRGB(x,y); int a = (p>>24)&0xff; int r = (p>>16)&0xff; int g = (p>>8)&0xff; int b = p&0xff; // Calculate average int avg = (r+g+b)/3; // Replace RGB value with avg p = (a<<24) | (avg<<16) | (avg<<8) | avg; getImg.setRGB(x, y, p); } } // End for JOptionPane.showMessageDialog(comboBoxPanel, "Gray Scale Filter has been applied. Save to view!"); // Write image try { f = output; ImageIO.write(getImg, "png", f); } catch(IOException ex){ System.out.println(ex); } // End try-catch } // End actionPerformed }); //End ActionListener
Mirror method that doesn’t work:
mirrored.setMnemonic('M'); // Hot Key // ActionListener for mirror button mirrored.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { File f = selFile1; BufferedImage res = null; try{ getImg = ImageIO.read(f); res = ImageIO.read(f); } catch(IOException ex){ System.out.println(ex); } // End try-catch // Get source image dimension int width = getImg.getWidth(); int height = getImg.getHeight(); //BufferedImage for mirror image res = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); //create mirror image pixel by pixel for(int y = 0; y < height; y++){ for(int lx = 0, rx = width - 1; lx < width; lx++, rx--){ // lx starts from the left side of the image // rx starts from the right side of the image // Get source pixel value int p = getImg.getRGB(lx, y); // Set mirror image pixel value - both left and right res.setRGB(rx, y, p); } } // End for JOptionPane.showMessageDialog(comboBoxPanel, "Mirrored Filter has been applied. Save to view!"); // Write image try{ f = output; ImageIO.write(res, "png", f); } catch(IOException ex){ System.out.println(ex); } // End try-catch } // End actionPerformed }); // End actionListener
GUI (For Reference):
Advertisement
Answer
So, speculation, you start out by doing…
File f = selFile1; BufferedImage res = null; try { getImg = ImageIO.read(f); res = ImageIO.read(f); } catch (IOException ex) { System.out.println(ex); } // End try-catch
And you end by doing this…
// Write image try { f = output; ImageIO.write(res, "png", f); } catch (IOException ex) { System.out.println(ex); } // End try-catch
But, getImg
is still pointing to the source (unmodified) image. If you’re using this to display the result to the user, then you’re displaying the wrong image. Based on you other “filter” operations, you’re modifying the getImg
directly.
Now, having said that, your code is, questionable, at best.
Let me explain…
File f = selFile1; BufferedImage res = null; try { getImg = ImageIO.read(f); res = ImageIO.read(f); } catch (IOException ex) { System.out.println(ex); } // End try-catch
How do you know selFile1
is not null
or that it points to a valid File
? You’ve done no checking here. Also, what’s the point of reading the file twice, especially when you do res = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
immediately after it?
This raises another question, what happens if the image loading fails? You carry on trying to use the getImg
reference anyway, which may contain “dirty” data or worse, be null
.
Instead, I might do something more like…
if (selFile1 == null) { // Show error message // Use JOptionPane to show message to user return; } try { BufferedImage sourceImage = ImageIO.read(selFile1); // Get source image dimension int width = sourceImage.getWidth(); int height = sourceImage.getHeight(); //BufferedImage for mirror image BufferedImage mirroredImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); //create mirror image pixel by pixel for (int y = 0; y < height; y++) { for (int lx = 0, rx = width - 1; lx < width; lx++, rx--) { // lx starts from the left side of the image // rx starts from the right side of the image // Get source pixel value int p = sourceImage.getRGB(lx, y); // Set mirror image pixel value - both left and right mirroredImage.setRGB(rx, y, p); } } // End for JOptionPane.showMessageDialog(comboBoxPanel, "Mirrored Filter has been applied. Save to view!"); // Write image ImageIO.write(mirroredImage, "png", selFile1); } catch (IOException ex) { ex.printStackTrace(); // Use JOptionPane to show message to user } // End try-catch
Now you could also isolate the write within a inner try-catch
, but the point is try and do some preemptive checking to prevent known issues from crashing your code.
Oh, and you might find…
BufferedImage mirrored = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = mirrored.createGraphics(); g2d.scale(-1, 1); g2d.translate(-source.getWidth(), 0); g2d.drawImage(source, 0, 0, null); g2d.dispose();
And much simpler way to mirror an image