Image Editor
EAS PEMROGRAMAN BERBASIS OBJEK (PBO)
Disini saya akan membuat image editor dengan melanjutkan postingan saya sebelumnya yang berupa image viewer. Selain menambahkan filter, disini saya akan menambahkan seperti resize, zoom in dan zoom out, rotate, dan flip. Sebelumnya saya akan menjelaskan desain interface dan class diagram nya yang berupa gambar, yaitu :
Menu terdiri dari 3 yaitu file yang berisi open, save as, undo, dan quit, fiter yang berisi darker, brighter, dan threshold, & edit yang berisi rotate by 90 CW, rotate by 180 CW, rotate by 270 CW, flip horizontally, dan flip vertically. Resize image terdiri dari 2, smaller untuk mengecilkan dan larger untuk memperbesar. Lalu ada zoom yang terdiri dari zoom in, zoom out, dan reset.
Class diagram terdiri dari 11 class yaitu ImageViewer, HistoryManager, ImageFileManager, ImagePanel, OFImage, dan Filter Class sendiri yang terdiri dari 5 class yaitu : FlipVerticallyFilter, ThresholdFiter, LighterFilter, DarkerFilter, dan MirrorFilter. ImageViewer di dalamnya terdapat editor untuk resize, zoom, filter, flip, dan rotate. Untuk flip sendiri memanfaatkan MirrorFilter class (untuk flip horizontically) dan FlipVerticallyFilter class (untuk flip vertically).
Berikut source code dan tampilan akhirnya :
1. Source Code ImageViewer
/**
* Write a description of class ImageViewer here.
*
* @author Yuki Yanuar Ratna
* @version 1.0
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.io.File;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageViewer
{
private static final String VERSION = "Version 2.0";
private static JFileChooser fileChooser= new JFileChooser(System.getProperty("user.dir"));
private static final String DEGREE = "\u00b0";
private JFrame frame;
private ImagePanel imagePanel;
private JLabel filenameLabel;
private JLabel statusLabel;
private JButton smallerButton;
private JButton largerButton;
private JLabel zoomLabel;
private JButton zoomInButton;
private JButton zoomOutButton;
private JButton zoomReset;
private JSlider zoomSlider;
private JLabel zoomValue;
private OFImage currentImage;
private JScrollPane scrollPanel;
private List<Filter> filters;
private HistoryManager historyMan;
private JFrame rFrame;
private JSlider rotateSlider;
private JLabel rotateDegrees;
private JButton rotateOK;
boolean click;
boolean changedH;
boolean changedW;
double zoom=100;
/**
* Create an ImageViewer show it on screen.
*/
public ImageViewer()
{
currentImage = null;
historyMan = new HistoryManager();
filters = createFilters();
makeFrame();
zoom =100;
}
// ---- implementation of menu functions ----
/**
* Open function: open a file chooser to select a new image file.
*/
private void openFile()
{
int returnVal = fileChooser.showOpenDialog(frame);
if (returnVal != JFileChooser.APPROVE_OPTION)
{
return;
}
File selectedFile = fileChooser.getSelectedFile();
currentImage = ImageFileManager.loadImage(selectedFile);
if (currentImage == null)
{
JOptionPane.showMessageDialog(frame,"The file was not in a recognized image file format.","Image Load Error",JOptionPane.ERROR_MESSAGE);
return;
}
historyMan.eraseAll();
historyMan.add(currentImage);
imagePanel.setImage(currentImage);
imagePanel.saveOriginal();
showStatus("File loaded.");
frame.pack();
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(d.width/2 - frame.getWidth()/2, d.height/2 - frame.getHeight()/2);
scrollPanel.getViewport().revalidate();
activateButtons();
resetSlider();
}
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 applyFilter(Filter filter)
{
if (currentImage != null)
{
filter.apply(currentImage);
frame.repaint();
}
}
private void showAbout()
{
JOptionPane.showMessageDialog(frame,"ImageViewer\n" + VERSION, "About ImageViewer",JOptionPane.INFORMATION_MESSAGE);
}
private void showFilename (String filename)
{
if (filename == null)
{
filenameLabel.setText("No file displayed.");
}
else
{
filenameLabel.setText("File: " + filename);
}
}
private void showStatus(String text)
{
statusLabel.setText(text);
}
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();
}
}
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 rotate(int angle){
if (currentImage!=null)
{
double sin = Math.abs(Math.sin(Math.toRadians(angle)));
double cos = Math.abs(Math.cos(Math.toRadians(angle)));
int w = currentImage.getWidth();
int h = currentImage.getHeight();
int neww = (int) Math.floor(w*cos + h*sin);
int newh = (int) Math.floor(h*cos + w*sin);
BufferedImage rotated = new BufferedImage(neww, newh, currentImage.getType());
Graphics2D g = rotated.createGraphics();
g.translate((neww-w)/2, (newh-h)/2);
g.rotate(Math.toRadians(angle), w/2, h/2);
g.drawImage(currentImage,null,0,0);
g.dispose();
currentImage=new OFImage(rotated);
imagePanel.setImage(currentImage);
imagePanel.saveOriginal();
scrollPanel.getViewport().revalidate();
historyMan.add(currentImage);
showStatus("Rotated by "+angle+DEGREE);
}
else
showStatus("No image loaded!");
}
private void zoomInBy10(){
imagePanel.zoom(zoom+10);
zoom=zoom+10;
}
private void zoomOutBy10(){
imagePanel.zoom(zoom-10);
zoom=zoom-10;
}
private void zoomByFactor(int fact){
imagePanel.zoom(fact);
zoom=fact;
}
private void activateButtons(){
zoomInButton.setEnabled(true);
zoomOutButton.setEnabled(true);
zoomReset.setEnabled(true);
zoomSlider.setEnabled(true);
}
private void deactivateButtons(){
zoomInButton.setEnabled(false);
zoomOutButton.setEnabled(false);
zoomReset.setEnabled(false);
zoomSlider.setEnabled(false);
}
private void setButtonsEnabled()
{
smallerButton.setEnabled(true);
largerButton.setEnabled(true);
}
private void resetSlider(){
click=true;
zoomSlider.setValue(100);
zoom=100;
zoomValue.setText(""+zoom+"%");
}
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"));
return filterList;
}
private void refreshFrame(){
frame.repaint();
}
// ---- 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(12, 12, 12, 12));
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));
//Create two labels at top and bottom
JPanel zoomPanel=new JPanel();
zoomPanel.setLayout(new GridLayout(0,1));
zoomLabel = new JLabel("Zoom:");
zoomLabel.setHorizontalAlignment(SwingConstants.CENTER);
zoomLabel.setVerticalAlignment(SwingConstants.CENTER);
zoomPanel.add(zoomLabel);
zoomInButton = new JButton("Zoom In");
zoomInButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if ((zoom>=10)&&(zoom<=490)){
click=true;
zoomInBy10();
zoomValue.setText(""+(zoom)+"%");
zoomSlider.setValue(zoomSlider.getValue()+10);
scrollPanel.getViewport().revalidate();
}
}
});
zoomPanel.add(zoomInButton);
zoomOutButton = new JButton("Zoom Out");
zoomOutButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if ((zoom>=20)&&(zoom<=500)){
click=true;
zoomOutBy10();
zoomValue.setText(""+(zoom)+"%");
zoomSlider.setValue(zoomSlider.getValue()-10);
scrollPanel.getViewport().revalidate();
}
}
});
zoomPanel.add(zoomOutButton);
zoomReset=new JButton("Reset");
zoomReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
click=true;
zoomByFactor(100);
zoomValue.setText(""+(zoom)+"%");
zoomSlider.setValue(100);
scrollPanel.getViewport().revalidate();
}
});
zoomPanel.add(zoomReset);
zoomSlider= new JSlider(10,500,100);
zoomSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if(click){
click=false;
}
else{
zoomByFactor(zoomSlider.getValue());
zoomValue.setText(""+zoom+"%");
scrollPanel.getViewport().revalidate();
}
}
});
zoomPanel.add(zoomSlider);
zoomValue= new JLabel(""+zoom+"%");
zoomPanel.add(zoomValue);
contentPane.add(zoomPanel, BorderLayout.EAST);
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);
// 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);
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);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/**
* 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);
// create the File manu
JMenu fileMenu = new JMenu("File");
menubar.add(fileMenu);
JMenuItem openItem = new JMenuItem("Open");
openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_MASK));
openItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { openFile(); }
});
fileMenu.add(openItem);
JMenuItem saveItem = new JMenuItem("Save as");
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_MASK));
saveItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { saveAs(); }
});
fileMenu.add(saveItem);
JMenuItem undoItem = new JMenuItem("Undo");
undoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, SHORTCUT_MASK));
undoItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
historyMan.undo();
OFImage img=historyMan.getCurrentVersion();
currentImage=img;
imagePanel.setImage(img);
imagePanel.saveOriginal();
refreshFrame();
scrollPanel.getViewport().revalidate();
}
});
fileMenu.add(undoItem);
JMenuItem quitItem = new JMenuItem("Quit");
quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_MASK));
quitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { quit(); }
});
fileMenu.add(quitItem);
JMenu Menu = new JMenu("Filter");
menubar.add(Menu);
for (final Filter filter : filters)
{
JMenuItem filterItem = new JMenuItem(filter.getName());
filterItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
applyFilter(filter);
}
});
Menu.add(filterItem);
}
JMenu fMenu = new JMenu("Edit");
menubar.add(fMenu);
JMenuItem rot1Item = new JMenuItem("Rotate by 90 CW");
rot1Item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { rotate(90); }
});
fMenu.add(rot1Item);
JMenuItem rot2Item = new JMenuItem("Rotate by 180 CW");
rot2Item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { rotate(180); }
});
fMenu.add(rot2Item);
JMenuItem rot3Item = new JMenuItem("Rotate by 270 CW");
rot3Item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { rotate(270); }
});
fMenu.add(rot3Item);
JMenuItem flip1Item = new JMenuItem("Flip Horizontally");
flip1Item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
applyFilter(new MirrorFilter("Flip Horizontally"));
}
});
fMenu.add(flip1Item);
JMenuItem flip2Item = new JMenuItem("Flip Vertically");
flip2Item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
applyFilter(new FlipVerticallyFilter("Flip vertically"));
}
});
fMenu.add(flip2Item);
}
}
2. Source Code HistoryManager
/**
* Write a description of class HistoryManager here.
*
* @author Yuki Yanuar Ratna
* @version 1.0
*/
import java.util.ArrayList;
public class HistoryManager {
private ArrayList<OFImage> history;
private int currentStep;
public HistoryManager() {
history=new ArrayList<OFImage>();
}
public void add(OFImage image){
OFImage img=new OFImage(image);
if(history.size()==0){
currentStep=0;
history.add(img);
return;
}
if((currentStep+1)<=history.size())
history.subList(currentStep+1, history.size()).clear();
history.add(img);
currentStep=currentStep+1;
}
public OFImage getCurrentVersion(){
return history.get(currentStep);
}
public Boolean canUndo(){
if (currentStep>0)
return true;
else
return false;
}
public Boolean canRedo(){
if (currentStep<(history.size()-1))
return true;
else
return false;
}
public void redo(){
if (canRedo())
currentStep=currentStep+1;
}
public void undo(){
if (canUndo())
currentStep=currentStep-1;
}
public void eraseAll(){
history.clear();
}
public int getCurrentStep(){
return currentStep;
}
public int getHistorySize(){
return history.size();
}
}
3. Source Code ImageFileManager
/**
* Write a description of class ImageFileManager here.
*
* @author Yuki Yanuar Ratna
* @version 1.0
*/
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;
import java.io.*;
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";
private static JFileChooser fileChooser = new JFileChooser(System.getProperty("user.dir"));
/**
* Open a file chooser and let the user select an image file in the file
* system. Then 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.
*
* @return The image object or null is it was not a valid image file.
*/
public static OFImage getImage()
{
int returnVal = fileChooser.showOpenDialog(null);
if(returnVal != JFileChooser.APPROVE_OPTION) {
return null; // cancelled
}
File selectedFile = fileChooser.getSelectedFile();
return loadImage(selectedFile);
}
/**
* Read an image file from disk and return it as a BufferedImage. 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 was not a valid image file.
*/
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;
}
}
}
4. Source Code ImagePanel
/**
* Write a description of class ImagePanel here.
*
* @author Yuki Yanuar Ratna
* @version 1.0
*/
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
public class ImagePanel extends JComponent
{
// The current width and height of this panel
private int width, height;
private BufferedImage original;
// 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();
}
}
public void saveOriginal(){
original=(OFImage) panelImage;
}
/**
* 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();
}
public void zoom(double factor){
double k=(factor)/100;
int newWidth = new Double(original.getWidth() * k).intValue();
int newHeight = new Double(original.getHeight() * k).intValue();
BufferedImage resized = new BufferedImage(newWidth, newHeight, original.getType());
Graphics2D g = resized.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(original, 0, 0, newWidth, newHeight, 0, 0, original.getWidth(),
original.getHeight(), null);
g.dispose();
OFImage img = new OFImage(resized);
setImage(img);
}
// 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);
}
}
}
5. Source Code OFImage
/**
* Write a description of class OFImage here.
*
* @author Yuki Yanuar Ratna
* @version 1.0
*/
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
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);
}
}
6. Source Code Filter
/**
* Write a description of class Filter here.
*
* @author Yuki Yanuar Ratna
* @version 2.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);
}
7. Source Code FlipVerticallyFilter
/**
* Write a description of class FlipVerticallyFilter here.
*
* @author Yuki Yanuar Ratna
* @version 1.0
*/
import java.awt.Color;
public class FlipVerticallyFilter extends Filter{
/**
* Constructor for objects of class MirrorFilter.
* @param name The name of the filter.
*/
public FlipVerticallyFilter(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 x = 0; x < width; x++) {
for(int y = 0; y < height / 2; y++) {
Color up = image.getPixel(x, y);
image.setPixel(x, y, image.getPixel(x,height - 1 - y));
image.setPixel(x,height - 1 - y,up);
}
}
}
}
8. Source Code ThresholdFilter
/**
* Write a description of class ThresholdFilter here.
*
* @author Yuki Yanuar Ratna
* @version 2.0
*/
import java.awt.Color;
/**
* An three-level gray-based threshold filter.
*
* @author Michael Kolling and David J Barnes
* @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);
}
}
}
}
}
9. Source Code LighterFilter
/**
* Write a description of class LighterFilter here.
*
* @author Yuki Yanuar Ratna
* @version 2.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());
}
}
}
}
10. Source Code DarkerFilter
/**
* Write a description of class DarkerFilter here.
*
* @author Yuki Yanuar Ratna
* @version 2.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());
}
}
}
}
11. Source Code MirrorFilter
/**
* Write a description of class MirrorFilter here.
*
* @author Yuki Yanuar Ratna
* @version 2.0
*/
import java.awt.Color;
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);
}
}
}
}
12. Tampilan Akhir
a. Tampilan awal
b.Ketika dimasukkan gambar
c. Ketika dikecilkan dengan menu smaller
d. Ketika dibesarkan dengan menu larger
e. Ketika dilakukan zoom in
f. Ketika dilakukan zoom out
g. Ketika diberi filter darker
h. Ketika diberi filter lighter
i. Ketika diberi filter threshold
j. Ketika dilakukan flip horizontally
k. Ketika dilakukan flip vertically
l. Ketika dilakukan salah satu rotate (90)
Sekian, semoga bermanfaat.
Komentar
Posting Komentar