UAS PBO
Di tugas UAS kali ini, kami membuat sebuah aplikasi photo editor sederhana.
Berikut tugas saya :
Dalam program saya, yang bisa dilakukan adalah
1. Mengupload gambar
2. Memberikan Filter
3. Memberikan teks
4. Meng-crop gambar
Classes :
Hasil saat mengopen picture:
Memberi Filter (GrayScale) :
Memberikan teks pada gambar:
Code :
ImageViewer :
SolarizeFilter :
LighterFilter :
PixelizeFilter :
InvertFilter :
Filter:
SmoothFilter:
ThresholdFilter:
MirrorFilter:
OFImage:
ImagePanel:
DarkerFilter:
ImageFileManager:
FishEyeFilter:
Berikut tugas saya :
Dalam program saya, yang bisa dilakukan adalah
1. Mengupload gambar
2. Memberikan Filter
3. Memberikan teks
4. Meng-crop gambar
Classes :
Hasil saat mengopen picture:
Memberi Filter (GrayScale) :
Memberikan teks pada gambar:
Code :
ImageViewer :
import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.*; import javax.swing.border.*; import java.io.File; import java.util.List; import java.util.ArrayList; import java.util.Iterator; /** * ImageViewer * * @author (Iman Afandy) * @tgl 12-12-2018) */ public class ImageViewer { // static fields: private static final String VERSION = "Version 3.1"; private static JFileChooser fileChooser = new JFileChooser(System.getProperty("user.dir")); // fields: private JFrame frame; private ImagePanel imagePanel; private JLabel filenameLabel; private JLabel statusLabel; private JButton smallerButton; private JButton largerButton; private JButton cropButton; private JButton textButton; private OFImage currentImage; private List<Filter> filters; /** * Create an ImageViewer and display its GUI on screen. */ public ImageViewer() { currentImage = null; filters = createFilters(); makeFrame(); } // ---- implementation of menu functions ---- /** * Open function: open a file chooser to select a new image file, * and then display the chosen image. */ private void openFile() { int returnVal = fileChooser.showOpenDialog(frame); if(returnVal != JFileChooser.APPROVE_OPTION) { return; // cancelled } File selectedFile = fileChooser.getSelectedFile(); currentImage = ImageFileManager.loadImage(selectedFile); if(currentImage == null) { // image file was not a valid image JOptionPane.showMessageDialog(frame, "The file was not in a recognized image file format.", "Image Load Error", JOptionPane.ERROR_MESSAGE); return; } imagePanel.setImage(currentImage); setButtonsEnabled(true); showFilename(selectedFile.getPath()); showStatus("File loaded."); frame.pack(); } /** * Close function: close the current image. */ private void close() { currentImage = null; imagePanel.clearImage(); showFilename(null); setButtonsEnabled(false); } /** * Save As function: save the current image to a file. */ private void saveAs() { if(currentImage != null) { int returnVal = fileChooser.showSaveDialog(frame); File selectedFile; if(returnVal != JFileChooser.APPROVE_OPTION) { selectedFile = new File("C://Users//user1//Pictures"); } else { selectedFile = fileChooser.getSelectedFile(); } ImageFileManager.saveImage(currentImage, selectedFile); showFilename(selectedFile.getPath()); } } /** * Quit function: quit the application. */ private void quit() { System.exit(0); } /** * Apply a given filter to the current image. * * @param filter The filter object to be applied. */ private void applyFilter(Filter filter) { if(currentImage != null) { filter.apply(currentImage); frame.repaint(); showStatus("Applied: " + filter.getName()); } else { showStatus("No image loaded."); } } /** * 'About' function: show the 'about' box. */ private void showAbout() { JOptionPane.showMessageDialog(frame, "ImageViewer\n" + VERSION, "About ImageViewer", JOptionPane.INFORMATION_MESSAGE); } /** * Add text to picture */ private void makeText() { if(currentImage != null) { int width = currentImage.getWidth(); int height = currentImage.getHeight(); int xPosition = Integer.parseInt(JOptionPane.showInputDialog("Posisi X")); int yPosition = Integer.parseInt(JOptionPane.showInputDialog("Posisi Y")); float fontSize = Float.parseFloat(JOptionPane.showInputDialog("Besar Font")); String addText = JOptionPane.showInputDialog("Ketik sesuatu.."); //String warna = JOptionPane.showInputDialog("Warna Font"); //Color c = Color.parseColor(warna); OFImage newImage = new OFImage(width, height); // copy pixel data into new image for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { Color col = currentImage.getPixel(x, y); newImage.setPixel(x, y, col); } } Graphics g = newImage.getGraphics(); g.setFont(g.getFont().deriveFont(fontSize)); //g.setColor(c); g.drawString(addText, xPosition, yPosition); g.dispose(); currentImage = newImage; imagePanel.setImage(currentImage); } } private void makeCrop() { if (currentImage != null) { int xa; xa = Integer.parseInt(JOptionPane.showInputDialog("xa")); int xb; xb = Integer.parseInt(JOptionPane.showInputDialog("xb")); int ya; ya = Integer.parseInt(JOptionPane.showInputDialog("ya")); int yb; yb = Integer.parseInt(JOptionPane.showInputDialog("yb")); int width = yb-ya; int height = xb-xa; OFImage newImage = new OFImage(width, height); for (int a = ya; a < yb ; a++) { for (int b = xa; b < xb ; b++) { newImage.setPixel(a - ya, b - xa, currentImage.getPixel(a, b)); } } currentImage = newImage; imagePanel.setImage(currentImage); frame.pack(); } } /** * Make the current picture larger. */ private void makeLarger() { if(currentImage != null) { // create new image with double size int width = currentImage.getWidth(); int height = currentImage.getHeight(); OFImage newImage = new OFImage(width * 2, height * 2); // copy pixel data into new image for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { Color col = currentImage.getPixel(x, y); newImage.setPixel(x * 2, y * 2, col); newImage.setPixel(x * 2 + 1, y * 2, col); newImage.setPixel(x * 2, y * 2 + 1, col); newImage.setPixel(x * 2+1, y * 2 + 1, col); } } currentImage = newImage; imagePanel.setImage(currentImage); frame.pack(); } } /** * Make the current picture smaller. */ private void makeSmaller() { if(currentImage != null) { // create new image with double size int width = currentImage.getWidth() / 2; int height = currentImage.getHeight() / 2; OFImage newImage = new OFImage(width, height); // copy pixel data into new image for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { newImage.setPixel(x, y, currentImage.getPixel(x * 2, y * 2)); } } currentImage = newImage; imagePanel.setImage(currentImage); frame.pack(); } } // ---- support methods ---- /** * Show the file name of the current image in the fils display label. * 'null' may be used as a parameter if no file is currently loaded. * * @param filename The file name to be displayed, or null for 'no file'. */ private void showFilename(String filename) { if(filename == null) { filenameLabel.setText("No file displayed."); } else { filenameLabel.setText("File: " + filename); } } /** * Show a message in the status bar at the bottom of the screen. * @param text The status message. */ private void showStatus(String text) { statusLabel.setText(text); } /** * Enable or disable all toolbar buttons. * * @param status 'true' to enable the buttons, 'false' to disable. */ private void setButtonsEnabled(boolean status) { smallerButton.setEnabled(status); largerButton.setEnabled(status); cropButton.setEnabled(status); textButton.setEnabled(status); } /** * Create a list with all the known filters. * @return The list of filters. */ private List<Filter> createFilters() { List<Filter> filterList = new ArrayList<Filter>(); filterList.add(new DarkerFilter("Darker")); filterList.add(new LighterFilter("Lighter")); filterList.add(new ThresholdFilter("Threshold")); filterList.add(new InvertFilter("Invert")); filterList.add(new SolarizeFilter("Solarize")); filterList.add(new SmoothFilter("Smooth")); filterList.add(new PixelizeFilter("Pixelize")); filterList.add(new MirrorFilter("Mirror")); filterList.add(new GrayScaleFilter("Grayscale")); filterList.add(new FishEyeFilter("Fish Eye")); return filterList; } // ---- Swing stuff to build the frame and all its components and menus ---- /** * Create the Swing frame and its content. */ private void makeFrame() { frame = new JFrame("ImageViewer"); JPanel contentPane = (JPanel)frame.getContentPane(); contentPane.setBorder(new EmptyBorder(6, 6, 6, 6)); makeMenuBar(frame); // Specify the layout manager with nice spacing contentPane.setLayout(new BorderLayout(6, 6)); // Create the image pane in the center imagePanel = new ImagePanel(); imagePanel.setBorder(new EtchedBorder()); contentPane.add(imagePanel, BorderLayout.CENTER); // Create two labels at top and bottom for the file name and status messages filenameLabel = new JLabel(); contentPane.add(filenameLabel, BorderLayout.NORTH); statusLabel = new JLabel(VERSION); contentPane.add(statusLabel, BorderLayout.SOUTH); // Create the toolbar with the buttons JPanel toolbar = new JPanel(); toolbar.setLayout(new GridLayout(0, 1)); smallerButton = new JButton("Smaller"); smallerButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { makeSmaller(); } }); toolbar.add(smallerButton); largerButton = new JButton("Larger"); largerButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { makeLarger(); } }); toolbar.add(largerButton); cropButton = new JButton("Crop"); cropButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { makeCrop(); } }); toolbar.add(cropButton); textButton = new JButton("Add Text"); textButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { makeText();} }); toolbar.add(textButton); // Add toolbar into panel with flow layout for spacing JPanel flow = new JPanel(); flow.add(toolbar); contentPane.add(flow, BorderLayout.WEST); // building is done - arrange the components showFilename(null); setButtonsEnabled(false); frame.pack(); // place the frame at the center of the screen and show Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); frame.setLocation(d.width/2 - frame.getWidth()/2, d.height/2 - frame.getHeight()/2); frame.setVisible(true); } /** * Create the main frame's menu bar. * * @param frame The frame that the menu bar should be added to. */ private void makeMenuBar(JFrame frame) { final int SHORTCUT_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); JMenuBar menubar = new JMenuBar(); frame.setJMenuBar(menubar); JMenu menu; JMenuItem item; // create the File menu menu = new JMenu("File"); menubar.add(menu); item = new JMenuItem("Open..."); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_MASK)); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { openFile(); } }); menu.add(item); item = new JMenuItem("Close"); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, SHORTCUT_MASK)); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { close(); } }); menu.add(item); menu.addSeparator(); item = new JMenuItem("Save As..."); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_MASK)); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { saveAs(); } }); menu.add(item); menu.addSeparator(); item = new JMenuItem("Quit"); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_MASK)); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { quit(); } }); menu.add(item); // create the Filter menu menu = new JMenu("Filter"); menubar.add(menu); for(final Filter filter : filters) { item = new JMenuItem(filter.getName()); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { applyFilter(filter); } }); menu.add(item); } // create the Help menu menu = new JMenu("Help"); menubar.add(menu); item = new JMenuItem("About ImageViewer..."); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { showAbout(); } }); menu.add(item); } }
SolarizeFilter :
import java.awt.Color; /** * An image filter to create a solarization effect. * * @author ImanAfandy * @tgl 12-12-2018 */ public class SolarizeFilter extends Filter { /** * Constructor for objects of class Solarize. * @param name The name of the filter. */ public SolarizeFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { int height = image.getHeight(); int width = image.getWidth(); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { Color pix = image.getPixel(x, y); int red = pix.getRed(); if(red <= 127) { red = 255 - red; } int green = pix.getGreen(); if(green <= 127) { green = 255 - green; } int blue = pix.getBlue(); if(blue <= 127) { blue = 255 - blue; } image.setPixel(x, y, new Color(red, green, blue)); } } } }
LighterFilter :
/** * An image filter to make the image a bit lighter. * * @author ImanAfandy * @tgl 12-12-2018 */ public class LighterFilter extends Filter { /** * Constructor for objects of class LighterFilter. * @param name The name of the filter. */ public LighterFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { int height = image.getHeight(); int width = image.getWidth(); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { image.setPixel(x, y, image.getPixel(x, y).brighter()); } } } }
PixelizeFilter :
import java.awt.Color; /** * An image filter to create a pixelization effect, like an enlarged * low-resolution digital image. * * * @author ImanAfandy * tgl 12/12/2018 */ public class PixelizeFilter extends Filter { /** * Constructor for objects of class PixelizeFilter. * @param name The name of the filter. */ public PixelizeFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { final int PIXEL_SIZE = 5; int width = image.getWidth(); int height = image.getHeight(); for(int y = 0; y < height; y += PIXEL_SIZE) { for(int x = 0; x < width; x += PIXEL_SIZE) { Color pix = image.getPixel(x, y); for(int dy = y; dy < y + PIXEL_SIZE; dy++) { for(int dx = x; dx < x + PIXEL_SIZE; dx++) { if( dx < width && dy < height ) image.setPixel(dx, dy, pix); } } } } } }
InvertFilter :
import java.awt.Color; /** * An image filter to invert colors. * * * @author ImanAfandy * tgl 12/12/2018 */ public class InvertFilter extends Filter { /** * Constructor for objects of class InvertFilter. * @param name The name of the filter. */ public InvertFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { int height = image.getHeight(); int width = image.getWidth(); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { Color pix = image.getPixel(x, y); image.setPixel(x, y, new Color(255 - pix.getRed(), 255 - pix.getGreen(), 255 - pix.getBlue())); } } } }
Filter:
/** * Filter * * @author ImanAfandy * tgl 12/12/2018 */ public abstract class Filter { private String name; /** * Create a new filter with a given name. * @param name The name of the filter. */ public Filter(String name) { this.name = name; } /** * Return the name of this filter. * * @return The name of this filter. */ public String getName() { return name; } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public abstract void apply(OFImage image); }
SmoothFilter:
import java.awt.Color; import java.util.List; import java.util.ArrayList; /** * An image filter to reduce sharp edges and pixelization. A bit like * a soft lens. * * @author ImanAfandy * tgl 12/12/2018 */ public class SmoothFilter extends Filter { private OFImage original; private int width; private int height; /** * Constructor for objects of class SmoothFilter. * @param name The name of the filter. */ public SmoothFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { original = new OFImage(image); width = original.getWidth(); height = original.getHeight(); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { image.setPixel(x, y, smooth(x, y)); } } } /** * Return a new color that is the smoothed color of a given * position. The "smoothed color" is the color value that is the * average of this pixel and all the adjacent pixels. * @param xpos The xposition of the pixel. * @param ypos The yposition of the pixel. * @return The smoothed color. */ private Color smooth(int xpos, int ypos) { List<Color> pixels = new ArrayList<Color>(9); for(int y = ypos - 1; y <= ypos + 1; y++) { for(int x = xpos - 1; x <= xpos + 1; x++) { if( x >= 0 && x < width && y >= 0 && y < height ) pixels.add(original.getPixel(x, y)); } } return new Color(avgRed(pixels), avgGreen(pixels), avgBlue(pixels)); } /** * @param pixels The list of pixels. * @return The average of all the red values in the given list of pixels. */ private int avgRed(List<Color> pixels) { int total = 0; for(Color color : pixels) { total += color.getRed(); } return total / pixels.size(); } /** * @param pixels The list of pixels. * @return The average of all the green values in the given list of pixels. */ private int avgGreen(List<Color> pixels) { int total = 0; for(Color color : pixels) { total += color.getGreen(); } return total / pixels.size(); } /** * @param pixels The list of pixels. * @return The average of all the blue values in the given list of pixels. */ private int avgBlue(List<Color> pixels) { int total = 0; for(Color color : pixels) { total += color.getBlue(); } return total / pixels.size(); } }
ThresholdFilter:
import java.awt.Color; /** * An three-level gray-based threshold filter. * * @author ImanAfandy * tgl 12/12/2018 */ public class ThresholdFilter extends Filter { /** * Constructor for objects of class ThresholdFilter. * @param name The name of the filter. */ public ThresholdFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { int height = image.getHeight(); int width = image.getWidth(); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { Color pixel = image.getPixel(x, y); int brightness = (pixel.getRed() + pixel.getBlue() + pixel.getGreen()) / 3; if(brightness <= 85) { image.setPixel(x, y, Color.BLACK); } else if(brightness <= 170) { image.setPixel(x, y, Color.GRAY); } else { image.setPixel(x, y, Color.WHITE); } } } } }
MirrorFilter:
import java.awt.Color; /** * An image filter to mirror (flip) the image horizontally. * * @author ImanAfandy * tgl 12/12/2018 */ public class MirrorFilter extends Filter { /** * Constructor for objects of class MirrorFilter. * @param name The name of the filter. */ public MirrorFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { int height = image.getHeight(); int width = image.getWidth(); for(int y = 0; y < height; y++) { for(int x = 0; x < width / 2; x++) { Color left = image.getPixel(x, y); image.setPixel(x, y, image.getPixel(width - 1 - x, y)); image.setPixel(width - 1 - x, y, left); } } } }
OFImage:
import java.awt.*; import java.awt.image.*; import javax.swing.*; /** * OFImage is a class that defines an image in OF (Objects First) format. * * @author ImanAfandy * tgl 12/12/2018 */ public class OFImage extends BufferedImage { /** * Create an OFImage copied from a BufferedImage. * @param image The image to copy. */ public OFImage(BufferedImage image) { super(image.getColorModel(), image.copyData(null), image.isAlphaPremultiplied(), null); } /** * Create an OFImage with specified size and unspecified content. * @param width The width of the image. * @param height The height of the image. */ public OFImage(int width, int height) { super(width, height, TYPE_INT_RGB); } /** * Set a given pixel of this image to a specified color. The * color is represented as an (r,g,b) value. * @param x The x position of the pixel. * @param y The y position of the pixel. * @param col The color of the pixel. */ public void setPixel(int x, int y, Color col) { int pixel = col.getRGB(); setRGB(x, y, pixel); } /** * Get the color value at a specified pixel position. * @param x The x position of the pixel. * @param y The y position of the pixel. * @return The color of the pixel at the given position. */ public Color getPixel(int x, int y) { int pixel = getRGB(x, y); return new Color(pixel); } }
ImagePanel:
import java.awt.*; import javax.swing.*; import java.awt.image.*; /** * An ImagePanel is a Swing component that can display an OFImage. * It is constructed as a subclass of JComponent with the added functionality * of setting an OFImage that will be displayed on the surface of this * component. * * @author ImanAfandy * tgl 12/12/2018 */ public class ImagePanel extends JComponent { // The current width and height of this panel private int width, height; // An internal image buffer that is used for painting. For // actual display, this image buffer is then copied to screen. private OFImage panelImage; /** * Create a new, empty ImagePanel. */ public ImagePanel() { width = 360; // arbitrary size for empty panel height = 240; panelImage = null; } /** * Set the image that this panel should show. * * @param image The image to be displayed. */ public void setImage(OFImage image) { if(image != null) { width = image.getWidth(); height = image.getHeight(); panelImage = image; repaint(); } } /** * Clear the image on this panel. */ public void clearImage() { Graphics imageGraphics = panelImage.getGraphics(); imageGraphics.setColor(Color.LIGHT_GRAY); imageGraphics.fillRect(0, 0, width, height); repaint(); } // The following methods are redefinitions of methods // inherited from superclasses. /** * Tell the layout manager how big we would like to be. * (This method gets called by layout managers for placing * the components.) * * @return The preferred dimension for this component. */ public Dimension getPreferredSize() { return new Dimension(width, height); } /** * This component needs to be redisplayed. Copy the internal image * to screen. (This method gets called by the Swing screen painter * every time it want this component displayed.) * * @param g The graphics context that can be used to draw on this component. */ public void paintComponent(Graphics g) { Dimension size = getSize(); g.clearRect(0, 0, size.width, size.height); if(panelImage != null) { g.drawImage(panelImage, 0, 0, null); } } }
DarkerFilter:
/** * An image filter to make the image a bit darker. * * @author ImanAfandy * tgl 12/12/2018 */ public class DarkerFilter extends Filter { /** * Constructor for objects of class DarkerFilter. * @param name The name of the filter. */ public DarkerFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { int height = image.getHeight(); int width = image.getWidth(); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { image.setPixel(x, y, image.getPixel(x, y).darker()); } } } }
ImageFileManager:
import java.awt.image.*; import javax.imageio.*; import java.io.*; /** * ImageFileManager is a small utility class with static methods to load * and save images. * * @author ImanAfandy * tgl 12/12/2018 */ public class ImageFileManager { // A constant for the image format that this writer uses for writing. // Available formats are "jpg" and "png". private static final String IMAGE_FORMAT = "jpg"; /** * Read an image file from disk and return it as an image. This method * can read JPG and PNG file formats. In case of any problem (e.g the file * does not exist, is in an undecodable format, or any other read error) * this method returns null. * * @param imageFile The image file to be loaded. * @return The image object or null is it could not be read. */ public static OFImage loadImage(File imageFile) { try { BufferedImage image = ImageIO.read(imageFile); if(image == null || (image.getWidth(null) < 0)) { // we could not load the image - probably invalid file format return null; } return new OFImage(image); } catch(IOException exc) { return null; } } /** * Write an image file to disk. The file format is JPG. In case of any * problem the method just silently returns. * * @param image The image to be saved. * @param file The file to save to. */ public static void saveImage(OFImage image, File file) { try { ImageIO.write(image, IMAGE_FORMAT, file); } catch(IOException exc) { return; } } }
FishEyeFilter:
import java.awt.Color; /** * An image filter to create an effect similar to a fisheye camera lens. * (Works especially well on portraits.) * * @author ImanAfandy * tgl 12/12/2018 */ public class FishEyeFilter extends Filter { // constants: private final static int SCALE = 20; // this defines the strenght of the filter private final static double TWO_PI = 2 * Math.PI; /** * Constructor for objects of class LensFilter. * @param name The name of the filter. */ public FishEyeFilter(String name) { super(name); } /** * Apply this filter to an image. * * @param image The image to be changed by this filter. */ public void apply(OFImage image) { int height = image.getHeight(); int width = image.getWidth(); OFImage original = new OFImage(image); int[] xa = computeXArray(width); int[] ya = computeYArray(height); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { image.setPixel(x, y, original.getPixel(x + xa[x], y + ya[y])); } } } /** * Compute and return an array of horizontal offsets for each pixel column. * These can then be applied as the horizontal offset for each pixel. */ private int[] computeXArray(int width) { int[] xArray = new int[width]; for(int i=0; i < width; i++) { xArray[i] = (int)(Math.sin( ((double)i / width) * TWO_PI) * SCALE); } return xArray; } /** * Compute and return an array of vertical offsets for each pixel row. * These can then be applied as the vertical offset for each pixel. */ private int[] computeYArray(int height) { int[] yArray = new int[height]; for(int i=0; i < height; i++) { yArray[i] = (int)(Math.sin( ((double)i / height) * TWO_PI) * SCALE); } return yArray; } }
Komentar
Posting Komentar