Nama : Bobbi Aditya
Kelas : PBO A
NRP : 05111740000099
Berikut adalah dokumentasi dari hasil pekerjaan EAS PBO saya, soal pertama adalah saya diberi tugas untuk merancang tampilan interface dari image viewer saya. Tampilan image viewer saya yang dulu adalah seperti ini
Dari tampilan awal yang seperti itu, saya ingin membuat menu-menu pada bagian kiri (bagian smaller,larger). Sehingga fitur-fitur image viewer saya akan terdapat pada bagian tersebut.
Rancangan class diagram saya berubah menjadi seperti dibawah ini:
Terdapat 7 class dalam imageviewer saya ini.
1. Image Viewer
Image Viewer adalah kelas utama dalam program ini, didalam kelas ini terdapat segala proses image viewer. Mulai dari open file,save file,close file, apply filter, membuat interfaces dll.
2.Image File Manager
Image File manager adalah kelas untuk open file dan save file ke disk komputer. Segala proses yang berhubungan dengan disk akan berada di dalam class ini.
3.Image Panel
Image Panel adalah kelas untuk menampilkan image yang telah di buat pada OFImage pada frame yang telah dibuat sehingga bisa dilihat oleh pengguna
4.OFImage
OFImage adalah kelas untuk mendefiniskan image menjadi object . Dalam hal ini, image dibuah menjadi bagian-bagian pixel yang kecil-kecil
5.Filter
Filter adalah superclass dari class-class filter yang ada. Filter-filter yang ada nantinya akan diberikan kepada OFImage yang telah dibuat.
6.EdgeFilter dan FishEyeFilter
Dua class tersebut adalah class-class filter yanng merupakan fungsi edit yang bisa digunakan
Dalam program diatas, filter-filter atau fungsi lainnya juga saya tambahan pada class imageviewer langsung, tanpa menggunakan class terlebih dahulu.
Berikut adalah kodingan dari masing-masing class yang saya buat:
1.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;
import javax.imageio.ImageIO;
/**
* ImageViewer is the main class of the image viewer application. It builds and
* displays the application GUI and initialises all other components.
*
* To start the application, create an object of this class.
*
* @author Bobbi Aditya
* @version 3.0
*/
public class ImageViewer
{
// static fields:
private static final String VERSION = "EAS PBO 2018";
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 makeDarker;
private JButton makeLighter;
private JButton Treshold;
private JButton Invert;
private JButton Mirror;
private JButton Grayscale;
private JButton Pixelize;
private JButton Reset;
private JButton Rotate;
private JButton Crop;
private JButton Text;
private OFImage currentImage;
private OFImage saveImage;
File selectedFile;
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
}
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);
}
/**
* 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 Darker()
{
if(currentImage != null){
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(width, height);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
newImage.setPixel(x, y, currentImage.getPixel(x, y).darker());
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void Lighter()
{
if(currentImage != null){
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(width, height);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
newImage.setPixel(x, y, currentImage.getPixel(x, y).brighter());
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void Treshold()
{
if(currentImage != null){
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(width, height);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
Color pixel = currentImage.getPixel(x, y);
int brightness = (pixel.getRed() + pixel.getBlue() + pixel.getGreen()) / 3;
if(brightness <= 85) {
newImage.setPixel(x, y, Color.BLACK);
}
else if(brightness <= 170) {
newImage.setPixel(x, y, Color.GRAY);
}
else {
newImage.setPixel(x, y, Color.WHITE);
}
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void Invert()
{
if(currentImage != null){
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(width, height);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
Color pix = currentImage.getPixel(x, y);
newImage.setPixel(x, y, new Color(255 - pix.getRed(),
255 - pix.getGreen(),
255 - pix.getBlue()));
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void GrayScale()
{
if(currentImage != null){
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(width, height);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
Color pix = currentImage.getPixel(x, y);
int avg = (pix.getRed() + pix.getGreen() + pix.getBlue()) / 3;
newImage.setPixel(x, y, new Color(avg, avg, avg));
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void Pixelize()
{
if(currentImage != null){
final int PIXEL_SIZE = 5;
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(width, height);
for(int y = 0; y < height; y += PIXEL_SIZE) {
for(int x = 0; x < width; x += PIXEL_SIZE) {
Color pix = currentImage.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 )
newImage.setPixel(dx, dy, pix);
}
}
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void Mirror()
{
if(currentImage != null){
int width = currentImage.getWidth();
int height = currentImage.getHeight();
OFImage newImage = new OFImage(width, height);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width / 2; x++) {
Color left = currentImage.getPixel(x, y);
newImage.setPixel(x, y, currentImage.getPixel(width - 1 - x, y));
newImage.setPixel(width - 1 - x, y, left);
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void rotate(int x)
{
if(currentImage != null)
{
double sin = Math.abs(Math.sin(Math.toRadians(x)));
double cos = Math.abs(Math.cos(Math.toRadians(x)));
int width = currentImage.getWidth();
int height = currentImage.getHeight();
int width_n = (int) Math.floor(width*cos + height*sin);
int height_n = (int) Math.floor(height*cos + width*sin);
BufferedImage r = new BufferedImage(width_n, height_n, currentImage.getType()); //BufferedImage(int width, int height, int imageType)
Graphics2D g = r.createGraphics();
g.translate((width_n-width)/2, (height_n-height)/2);
g.rotate(Math.toRadians(x), width/2, height/2);
g.drawImage(currentImage, null, 0, 0);
g.dispose();
currentImage=new OFImage(r);
imagePanel.setImage(currentImage);
}
}
private void Text()
{
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 Text yang ingin di input");
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.drawString(addText, xPosition, yPosition);
g.dispose();
currentImage = newImage;
imagePanel.setImage(currentImage);
}
}
private void Reset()
{
if(currentImage != null) {
currentImage= ImageFileManager.loadImage(selectedFile);
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 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);
makeDarker.setEnabled(status);
makeLighter.setEnabled(status);
Treshold.setEnabled(status);
Invert.setEnabled(status);
Mirror.setEnabled(status);
Pixelize.setEnabled(status);
Grayscale.setEnabled(status);
Reset.setEnabled(status);
Rotate.setEnabled(status);
Text.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 FishEyeFilter("Fish Eye"));
filterList.add(new EdgeFilter("Edge Detection"));
return filterList;
}
// ---- 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));
JLabel sizeLabel,spaceLabel,filterLabel;
sizeLabel = new JLabel("Size");
toolbar.add(sizeLabel);
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);
spaceLabel = new JLabel("");
toolbar.add(spaceLabel);
toolbar.add(spaceLabel);
filterLabel = new JLabel("Function");
toolbar.add(filterLabel);
makeDarker = new JButton("Darker");
makeDarker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Darker(); }
});
toolbar.add(makeDarker);
makeLighter = new JButton("Lighter");
makeLighter.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Lighter(); }
});
toolbar.add(makeLighter);
Text = new JButton("Text");
Text.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Text(); }
});
toolbar.add(Text);
Treshold = new JButton("Treshold");
Treshold.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Treshold(); }
});
toolbar.add(Treshold);
Invert = new JButton("Invert");
Invert.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Invert(); }
});
toolbar.add(Invert);
Mirror = new JButton("Mirror");
Mirror.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Mirror(); }
});
toolbar.add(Mirror);
Rotate = new JButton("Rotate");
Rotate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { rotate(90); }
});
toolbar.add(Rotate);
Grayscale = new JButton("Grayscale");
Grayscale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { GrayScale(); }
});
toolbar.add(Grayscale);
Pixelize = new JButton("Pixelize");
Pixelize.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Pixelize(); }
});
toolbar.add(Pixelize);
Reset = new JButton("Reset");
Reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { Reset(); }
});
toolbar.add(Reset);
// 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);
// create crop menu
//menu = new JMenu("Crop");
//menubar.add(menu);
//item = new JMenuItem("Crop");
// item.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) { Crop(); }
// });
//menu.add(item);
}
}
2.Image File Manager
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 Bobbi Aditya
* @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;
}
}
}
3.Image Panel
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 Bobbi Aditya
* @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.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);
}
}
}
4.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 Bobbi Aditya
* @version 2.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);
}
}
5.Filter
/**
* Filter is an abstract superclass for all image filters in this
* application. Filters can be applied to OFImages by invoking the apply
* method.
*
* @author Bobbi Aditya
* @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);
}
6.EdgeFilter
import java.awt.Color;
import java.util.List;
import java.util.ArrayList;
/**
* An image filter to detect edges and highlight them, a bit like
* a colored pencil drawing.
*
* @author Bobbi Aditya
* @version 1.0
*/
public class EdgeFilter extends Filter
{
private static final int TOLERANCE = 20;
private OFImage original;
private int width;
private int height;
/**
* Constructor for objects of class EdgeFilter.
* @param name The name of the filter.
*/
public EdgeFilter(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, edge(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 x position of the pixel.
* @param ypos The y position of the pixel.
* @return The smoothed color.
*/
private Color edge(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(255 - diffRed(pixels), 255 - diffGreen(pixels), 255 - diffBlue(pixels));
}
/**
* @param pixels The list of pixels to be averaged.
* @return The average of all the red values in the given list of pixels.
*/
private int diffRed(List<Color> pixels)
{
int max = 0;
int min = 255;
for(Color color : pixels) {
int val = color.getRed();
if(val > max) {
max = val;
}
if(val < min) {
min = val;
}
}
int difference = max - min - TOLERANCE;
if(difference < 0) {
difference = 0;
}
return difference;
}
/**
* @param pixels The list of pixels to be averaged.
* @return The average of all the green values in the given list of pixels.
*/
private int diffGreen(List<Color> pixels)
{
int max = 0;
int min = 255;
for(Color color : pixels) {
int val = color.getGreen();
if(val > max) {
max = val;
}
if(val < min) {
min = val;
}
}
int difference = max - min - TOLERANCE;
if(difference < 0) {
difference = 0;
}
return difference;
}
/**
* @param pixels The list of pixels to be averaged.
* @return The average of all the blue values in the given list of pixels.
*/
private int diffBlue(List<Color> pixels)
{
int max = 0;
int min = 255;
for(Color color : pixels) {
int val = color.getBlue();
if(val > max) {
max = val;
}
if(val < min) {
min = val;
}
}
int difference = max - min - TOLERANCE;
if(difference < 0) {
difference = 0;
}
return difference;
}
}
7.FishEyeFilter
import java.awt.Color;
/**
* An image filter to create an effect similar to a fisheye camera lens.
* (Works especially well on portraits.)
*
* @author Bobbi Aditya
* @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 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;
}
}
Berikut adalah tampilan awal saat saya menjalankan ImageViewer
Setelah foto terbuka, setiap fungsi yang ada di sebelah kiri semua sudah bisa dijalankan. Selain fungsi-fungsi tersebut, filter yang ada di bagian atas juga bisa dijalankan.
Berikut adalah contoh-contoh hasil dari beberapa fungsi yang dijalankan
Setelah melakukan berbagai filter edit, saya melakukan reset agar foto kembali ke bentuk awalnya
Sekian TerimaKasih :)
Comments
Post a Comment