Nama: Elkana Hans Widersen
NRP: 05111740000127
Kelas: PBO-A
1. Inilah rancangan interface dari image editor yang saya buat:
2. Berikut diagram dari kelas-kelas penyusun image editor saya beserta relasinya:
Image Panel
Image File Manager
OF Image
Filter
Darker Filter
Lighter Filter
Threshold Filter
Fish-eye Filter
NRP: 05111740000127
Kelas: PBO-A
1. Inilah rancangan interface dari image editor yang saya buat:
2. Berikut diagram dari kelas-kelas penyusun image editor saya beserta relasinya:
- Image Viewer: Kelas utama yang mengatur fitur-fitur utama dari image editor.
- Image Panel: Kelas swing untuk menampilkan gambar dalam format OF.
- Image File Manager: Mengatur fungsi load dan save.
- OF Image: Mendefinisikan gambar dalam format OF.
- Filter: Abstraksi dari filter-filter yang tersedia.
- Darker Filter: Berisi settingan filter Darker.
- Lighter Filter: Berisi settingan filter Lighter.
- Threshold Filter: Berisi settingan filter Threshold.
Fish-eye Filter: Berisi settingan filter Fish-eye.
3. Berikut implementasi dari kelas-kelas di atas:
- Image Viewer
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 is the main class of the image viewer application.
* It builds and displays the application GUI and
* initializes all other components.
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
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 textButton;
private OFImage currentImage;
private List<Filter> filters;
/**
* Create an ImageViewer and display its GUI on screen.
*/
public ImageViewer() {
currentImage = null;
filters = createFilters();
makeFrame();
}
// ---- 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);
if(returnVal != JFileChooser.APPROVE_OPTION) return; //cancelled
File selectedFile = fileChooser.getSelectedFile();
ImageFileManager.saveImage(currentImage, selectedFile);
showFilename(selectedFile.getPath());
}
}
/**
* Quit function: quit the application.
*/
private void quit() {
System.exit(0);
}
private void crop() {
if (currentImage != null) {
int width = currentImage.getWidth();
int height = currentImage.getWidth();
int x1 = Integer.parseInt(JOptionPane.showInputDialog("x1"));
int y1 = Integer.parseInt(JOptionPane.showInputDialog("y1"));
int x2 = Integer.parseInt(JOptionPane.showInputDialog("x2"));
int y2 = Integer.parseInt(JOptionPane.showInputDialog("y2"));
OFImage newImage = new OFImage(x2 - x1, y2 - y1);
for (int y = 0; y < y2 - y1; y++) {
for (int x = 0; x < x2 - x1; x++) {
newImage.setPixel(x, y, currentImage.getPixel(x + x1, y + y1));
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
/**
* Rotate Left function: flip the image 90 degrees counter-clockwise.
*/
private void rotateLeft() {
if(currentImage != null) {
// create new image with double size
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(height, width);
// 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(y, width - x - 1, col);
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
/**
* Rotate Right function: flip the image 90 degrees clockwise.
*/
private void rotateRight() {
if(currentImage != null) {
// create new image with double size
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(height, width);
// 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(height - y - 1, x, col);
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
/**
* Flip Horizontal function: flip the image horizontally.
*/
private void flipHorizontal() {
if(currentImage != null) {
// create new image with double size
int width = currentImage.getWidth();
int height = currentImage.getHeight();
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(width - x - 1, y);
newImage.setPixel(x, y, col);
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
/**
* Flip Vertical function: flip the image vertically.
*/
private void flipVertical() {
if(currentImage != null) {
// create new image with double size
int width = currentImage.getWidth();
int height = currentImage.getHeight();
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, height - y - 1);
newImage.setPixel(x, y, col);
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
/**
* 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);
}
/**
* 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();
}
}
private void insertText() {
JTextField xField = new JTextField(5);
JTextField yField = new JTextField(5);
JTextField zField = new JTextField(5);
JPanel myPanel = new JPanel();
myPanel.add(new JLabel("R"));
myPanel.add(xField);
myPanel.add(Box.createVerticalStrut(15)); // a spacer
myPanel.add(new JLabel("G"));
myPanel.add(yField);
myPanel.add(Box.createVerticalStrut(15)); // a spacer
myPanel.add(new JLabel("B"));
myPanel.add(zField);
if(currentImage != null) {
int width = currentImage.getWidth();
int height = currentImage.getHeight();
int xPosition = Integer.parseInt(JOptionPane.showInputDialog("Pixel Position X"));
int yPosition = Integer.parseInt(JOptionPane.showInputDialog("Pixel Position Y"));
float fontSize = Float.parseFloat(JOptionPane.showInputDialog("Font Size"));
String addText = JOptionPane.showInputDialog("Write Something..");
int result = JOptionPane.showConfirmDialog(null, myPanel, "Font Color", JOptionPane.OK_CANCEL_OPTION);
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);
}
}
int r = Integer.parseInt(xField.getText());
int gr = Integer.parseInt(yField.getText());
int b = Integer.parseInt(zField.getText());
Color c = new Color(r,gr,b);
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);
}
}
// ---- 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 message to be displayed.
*/
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);
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 FishEyeFilter("Fish Eye"));
return filterList;
}
private void saveHistory(OFImage img) {
}
// ---- swing stuff to build the frame and all its components ----
/**
* 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 message
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);
textButton = new JButton("Insert Text");
textButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { insertText(); }
});
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 shortcutMask = 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, shortcutMask));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { openFile(); }
});
menu.add(item);
item = new JMenuItem("Close");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, shortcutMask));
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, shortcutMask));
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, shortcutMask));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { quit(); }
});
menu.add(item);
// create the Edit menu
menu = new JMenu("Edit");
menubar.add(menu);
item = new JMenuItem("Crop");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.SHIFT_MASK));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { crop(); }
});
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Rotate Left");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { rotateLeft(); }
});
menu.add(item);
item = new JMenuItem("Rotate Right");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { rotateRight(); }
});
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Flip Horizontal");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { flipHorizontal(); }
});
menu.add(item);
item = new JMenuItem("Flip Vertical");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { flipVertical(); }
});
menu.add(item);
menu.addSeparator();
// 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);
}
}
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 (Elkana Hans Widersen)
* @version 1.0
*/
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.lightGray);
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
* wants this component displayed.)
*
* @param g The graphics context that can be used to draw on this component.
*/
public void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
Dimension size = getSize();
g2D.clearRect(0, 0, size.width, size.height);
if(panelImage != null) g2D.drawImage(panelImage, 0, 0, null);
}
}
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
/**
* ImageFileManager is a small utility class with static methods
* to load and save images.
*
* The files on disk can be in JPG or PNG image format.
* For files written by this class, the format is determined
* by the constant IMAGE_FORMAT.
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
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;
}
}
}
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
/**
* OFImage is a class that defines an image
* in OF (Objects First) format.
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
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);
}
}
/**
* Filter is an abstract superclass for all image filters in this
* application. Filters can be applied to OFImages by invoking
* the apply method.
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
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);
}
/**
* An image filter to make the image a bit darker. (versi 3.0)
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
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());
}
}
}
}
/**
* An image filter to make the image a bit lighter. (versi 3.0)
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
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());
}
}
}
}
import java.awt.Color;
/**
* An three-level gray-based threshold filter. (versi 3.0)
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
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);
}
}
}
}
import java.awt.Color;
/**
* An image filter to create an effect similar
* to a fisheye camera lens.
* (Works especially well on portraits.)
*
* @author (Elkana Hans Widersen)
* @version 1.0
*/
public class FishEyeFilter extends Filter {
// constants:
private final static int scale = 20; // this defines the strenght of the filter
private final static double doublePi = 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) * doublePi) * 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) * doublePi) * scale);
}
return yArray;
}
}
Komentar
Posting Komentar