Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Need help creating the FlipVerticalFilter, GrayScale1, GrayScale2, rotate clockwise, rotate counter-clockwise, Gaussian, laplacian, unsharpmasking, and edgy classes. ------------------------------------------------------------------------------- SnapShop.java import java.awt.*; import java.awt.event.*; import java.awt.image.*;

image text in transcribedimage text in transcribedimage text in transcribedimage text in transcribed

Need help creating the FlipVerticalFilter, GrayScale1, GrayScale2, rotate clockwise, rotate counter-clockwise, Gaussian, laplacian, unsharpmasking, and edgy classes.

-------------------------------------------------------------------------------

SnapShop.java

import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.*; import javax.swing.filechooser.*; import java.io.*;
public class SnapShop { protected JFrame win; private FileLoader fl; private FilterButtons fb; private ImagePanel ip; private RenderingDialog rd;
public SnapShop() { win = new JFrame("CSC 143 - SnapShop"); // Create all the necessary components and add them to the frame ip = new ImagePanel(this); win.add(ip, BorderLayout.CENTER); fl = new FileLoader(this); win.add(fl, BorderLayout.NORTH); fb = new FilterButtons(this); win.add(fb, BorderLayout.WEST); rd = new RenderingDialog(win); SnapShopConfiguration.configure(this); win.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); win.pack(); win.setVisible(true); }
public void addFlipHorizontalFilter(Filter f) { fb.addFilter(f, "Flip Horizontal"); }
public void addFlipVerticalFilter(Filter f) { fb.addFilter(f, "Flip Vertical"); }
public void addGrayScale1Filter(Filter f) { fb.addFilter(f, "Gray Scale 1"); }
public void addGrayScale2Filter(Filter f) { fb.addFilter(f, "Gray Scale 2"); }
public void addGaussianFilter(Filter f) { fb.addFilter(f, "Gaussian"); }
public void addLaplacianFilter(Filter f) { fb.addFilter(f, "Laplacian"); }
public void addUnsharpMaskingFilter(Filter f) { fb.addFilter(f, "Unsharp Masking"); }
public void addEdgyFilter(Filter f) { fb.addFilter(f, "\"Edgy\""); }
public void addRotateClockwiseFilter(Filter f) { fb.addFilter(f, "Rotate Clockwise"); }
public void addRotateCounterClockwiseFilter(Filter f) { fb.addFilter(f, "Rotate Counter-Clockwise"); }
public void setDefaultFilename(String filename) { fl.setDefaultFilename(filename); }
public static void main(String[] args) { SnapShop s = new SnapShop(); }
protected void showWaitDialog() { rd.pack(); rd.setVisible(true); }
protected void hideWaitDialog() { rd.setVisible(false); }
protected ImagePanel getImagePanel() { return ip; }
private class FileLoader extends JPanel implements ActionListener { private JLabel lbl; private JTextArea filenameBox; private ImagePanel ip; private SnapShop snapshop; private JFileChooser pick; private MouseListener mouse = new MouseAdapter() { public void mouseClicked(MouseEvent e) { if(pick.showOpenDialog(snapshop.win) == JFileChooser.APPROVE_OPTION) { String filename = pick.getSelectedFile().getAbsolutePath(); filenameBox.setText(filename); loadFile(filename); } } };
public FileLoader(SnapShop s) { super(new FlowLayout()); pick = new JFileChooser(); pick.setFileFilter(new FileNameExtensionFilter("Image files", "jpg", "gif", "png", "bmp")); snapshop = s; this.ip = s.getImagePanel(); lbl = new JLabel("Click to enter file name: "); lbl.addMouseListener(mouse); add(lbl); filenameBox = new JTextArea(1, 50); filenameBox.addMouseListener(mouse); add(filenameBox); JButton loadButton = new JButton("Load"); loadButton.addActionListener(this); add(loadButton); }
public void actionPerformed(ActionEvent e) { loadFile(filenameBox.getText()); } private void loadFile(String filename) { try { ip.loadImage(filename); } catch (Exception ex) { JOptionPane.showMessageDialog(snapshop.win, "Could not open file", "Error", JOptionPane.ERROR_MESSAGE); } } public void setDefaultFilename(String filename) { filenameBox.setText(filename); } }
private class FilterButtons extends JPanel { private JPanel buttons; private SnapShop snapshop; private ImagePanel ip; public FilterButtons(SnapShop s) { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); buttons = new JPanel(new GridLayout(9,1)); snapshop = s; ip = s.getImagePanel(); add(buttons); add(Box.createVerticalGlue()); } public void addFilter(Filter f, String description) { JButton filterButton = new JButton(description); filterButton.addActionListener(new FilterButtonListener(this, f)); buttons.add(filterButton); snapshop.win.pack(); } public void applyFilter(Filter f) { ip.applyFilter(f); } // inner, inner class private class FilterButtonListener implements ActionListener { private FilterButtons fb; private Filter f; public FilterButtonListener(FilterButtons fb, Filter f) { this.fb = fb; this.f = f; } public void actionPerformed(ActionEvent e) { fb.applyFilter(f); } } }
private class ImagePanel extends JPanel { private BufferedImage bi; private SnapShop snapshop; public ImagePanel(SnapShop s) { bi = null; snapshop = s; } public void loadImage(String filename) { Image img = Toolkit.getDefaultToolkit().getImage(filename); try { MediaTracker tracker = new MediaTracker(this); tracker.addImage(img, 0); tracker.waitForID(0); } catch (Exception e) {} int width = img.getWidth(this); int height = img.getHeight(this); bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D biContext = bi.createGraphics(); biContext.drawImage(img, 0, 0, null); setPreferredSize(new Dimension(bi.getWidth(), bi.getHeight())); revalidate(); snapshop.win.pack(); snapshop.win.repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); if (bi != null) { g.drawImage(bi, 0, 0, this); } }
public void applyFilter(Filter f) { if (bi == null) { return; } PixelImage newImage = new PixelImage(bi); snapshop.showWaitDialog(); try { f.filter(newImage); } catch(IllegalStateException e) { JOptionPane.showMessageDialog(win, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } catch (Exception e) { e.printStackTrace(System.err); } snapshop.hideWaitDialog(); bi = newImage.getImage(); repaint(); } }
private class RenderingDialog extends JFrame { public RenderingDialog(JFrame parent) { super("Please Wait"); Point p = parent.getLocation(); setLocation(p.x + 100, p.y + 100); this.getContentPane().add(new JLabel("Applying filter, please wait..."), BorderLayout.CENTER); } } }

----------------------------------------------------------------------

SnapShopConfiguration.java

public class SnapShopConfiguration {
 public static void configure(SnapShop theShop) { theShop.setDefaultFilename(""); theShop.addFlipHorizontalFilter(new FlipHorizontalFilter()); theShop.addFlipVerticalFilter(new FlipVerticalFilter()); theShop.addGrayScale1Filter(null); // theShop.addGrayScale2Filter(null); // theShop.addGaussianFilter(null); // theShop.addLaplacianFilter(null); // theShop.addUnsharpMaskingFilter(null); // theShop.addEdgyFilter(null); // theShop.addRotateClockwiseFilter(null); // theShop.addRotateCounterClockwiseFilter(null); } }

------------------------------------------------------------------------------------------------------------------

PixelImage.java

import java.awt.image.*;
public class PixelImage { private BufferedImage myImage; private int width; private int height; 
public PixelImage(BufferedImage bi) { // initialise instance variables this.myImage = bi; this.width = bi.getWidth(); this.height = bi.getHeight(); }
public int getWidth() { return this.width; }
public int getHeight() { return this.height; }
public Pixel[][] getData() {
Raster r = this.myImage.getRaster(); Pixel[][] data = new Pixel[r.getHeight()][r.getWidth()]; int[] samples = new int[3]; // Translates from java image data to Pixel data for (int row = 0; row  
public void setData(Pixel[][] data) throws IllegalArgumentException { WritableRaster wr = this.myImage.getRaster(); if (data.length != wr.getHeight()) { throw new IllegalArgumentException("Array size does not match"); } else if (data[0].length != wr.getWidth()) { throw new IllegalArgumentException("Array size does not match"); } // Translates from an array of Pixel data to java image data for (int row = 0; row  
 public BufferedImage getImage() { return this.myImage; } }

-----------------------------------------------------------------------------------------------------------------------

Pixel.java

public class Pixel { public static final int RED = 0, GREEN = 1, BLUE = 2; // RGB color values for this pixel (0-255) public int[] rgb; 
public Pixel(int red, int green, int blue) { if ((red  255) || (green  255) || (blue  255)) { throw new IllegalArgumentException("bad RGB value for Pixel"); } rgb = new int[3]; rgb[RED] = red; rgb[GREEN] = green; rgb[BLUE] = blue; } }

------------------------------------------------------------------------------------------------------------------------------

Filter.java

public interface Filter {
 void filter(PixelImage theImage); } 

--------------------------------------------------------------------------------------------------------------------------------

FlipHorizontalFilter.java

public class FlipHorizontalFilter implements Filter {
public void filter(PixelImage theImage) { Pixel[][] data = theImage.getData(); for (int row = 0; row   Simple Transformations There are two simple transformations you shall add to SnapShop: flipping the image vertically and creating a gray-scale image. Flip Vertical Create a new class FlipVerticalFilter. This class shall implement the Filter interface. You can use FlipHorizontalFilter as a model. Make sure that the comments make sense. Add the FlipVerticalFilter to SnapShop. You can do this by removing the comment marker on line 20 of SnapShop Configuration and adding an appropriate argument to the method call. You can test your implementation at this time. Notes:  Assume that the image is rectangular, that is that all of the rows are the same length.  The flip horizontal and flip vertical transformations are their own inverses. That is, applying either of these filters twice will result in the original image.  You can reload the image in SnapShop by simply clicking the Load button.  For the purposes of testing, keep the files relatively small, say less than 50 K.  It is a good idea to give complete filenames. You can use a forward slash for indicating folders, even on Windows. Gray Scale The second simple transform is to convert the picture to gray scale. That means that all three color components (red, green, and blue) shall have the same value after the filter is applied. Let's call this value the gray value. The standard gray scale algorithm sets the gray value to the sum of 30% of the red value, 59% of the green value, and 11% of the blue value. We will call this Gray Scale 1. A commonly used approximation sets the gray value to 11/32 of the red value, 16/32 of the green value, and 5/32 of the blue value. This calculation is used because it is easy to implement using integer arithmetic. We will call this Gray Scale 2. | gray = (11 * red + 16* green + 5 * blue) / 32 Both of these transforms can be implemented by directly modifying the array of pixels. Rotational Transformations These are conceptually quite straight-forward, as shown in the test cases below. Rotate Clockwise and Rotate Counter-Clockwise There is a major wrinkle with these two transforms. The implementation of Pixellmage requires that when the setData method is called, the dimensions of the array of Pixels matches the original dimensions of the image. Therefore, these transformations can only be applied to square images. If the Pixel array does not have the same dimensions, the call to setData fails with an illegalArgumentException. The implementation of these filters needs to deal with the requirement for a square image. If the image is square, the filter should apply the rotational transform. If the image is not square, there is no need to do any processing; the filter can raise IllegalStateException. The SnapShop code is set up to handle this exception displaying a message dialog box, which will display the exception message. Error  Only square images can be rotated. OK Note: One of the extra-credit options is to update the Pixellmage code to allow the rotation of non-square images. In this case, the rotational filters should not throw an IllegalState Exception. Edgy -1-1-1 -1 9-1 -1-1-1 This is the Laplacian transform added to the original pixel. The sum of the weights is 1, so there is no need for scaling. However, the values must still be checked against the range, 0 - 255, and corrected if needed. 3x3 Transformations The next set of transformations are a bit more complicated. They are: Gaussian, Laplacian, Unsharp Masking, and Edgy. In these transformations, the value of a pixel is calculated using the original pixel and its immediate neighbors. That is, a 3x3 grid of pixels is used to calculate the value for a pixel. The red, green, and blue values are handled separately; that is, the new red value is calculated from the old red values; the new green value, from the old green values; and the new blue value, from the old blue values. The four transforms compute the new pixel values as a weighted average of the old values. The only difference between these transforms is the weights that are used. When you implement these transforms, consider refactoring rather than having completely separate calculations for each of the transforms. There are a couple ways to do this. Please feel free to discuss the options in the forum. Here are the weights to use for the 3x3 transformations, with some additional notes. Gaussian 121 242 121 The weights total 16. So, after computed the weighted sum, the total must be divided by 16 to bring the value back into the range, 0 - 255. The effect of this filter is to blur the image. Laplacian -1-1-1 -1 8-1 -1-1-1 In this case, the sum of the weights is 0. There is no need to scale the sum. However, the values must remain within the range, 0 - 255. So, if the sum is less than 0, use 0 rather than the calculated value. Similarly, if the sum is greater than 255, use 255 rather than the calculated value. This transform detects edges and highlights them. Unsharp Masking -1 -2 -1 -2 28-2 -1 -2 -1 This transform is created by multiplying the cell value by 32 and subtracting the Gaussian transform. The sum of the weights is 16, so the weighted sum must be scaled by 16 to bring it into range. As with the Laplacian transform, the scaled values must then be adjusted to insure that they are within the range, 0 - 255. This transform can lessen the blurring in an image

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions