Image Editor
Nama : Timothyus Tanner
NRP : 05111740000103
Kelas : PBO - A
1. Gambarkan rancangan interfacenya.
2. Gambarkan dan jelaskan Class Diagram penyusun dari image viewer yang akan dibuat.
Class ImageViewer = ImageViewer adalah kelas utama aplikasi penampil gambar. Ini membangun dan menampilkan aplikasi GUI dan menginisialisasi semua komponen lainnya.
Class ImagePanel = ImagePanel adalah komponen Swing yang dapat menampilkan OFImage.
Class ImageFileManager = ImageFileManager adalah kertas utilitas kecil dengan metode statis untuk memuat dan simpan gambar.
Class OFImage = OFImage adalah kelas yang mendefinisikan gambar dalam format OF (Objects First)
3. Implementasikan ke dalam program dan buat link nya di posting blog ini.
Source Code :
1. Image Viewer
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.io.File;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import javax.imageio.*;
import java.io.*;
/**
* Nama : Timothyus Tanner
* NRP : 05111740000103
* Kelas : PBO - A
* 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 Michael Kolling and David J Barnes
* @version 1.0
*/
public class ImageViewer
{
// static fields:
private static final String VERSION = "Version 1.0";
private static JFileChooser fileChooser = new JFileChooser(System.getProperty("user.dir"));
// fields:
private JFrame frame;
private ImagePanel imagePanel;
private JLabel filenameLabel;
private JLabel statusLabel;
private OFImage currentImage;
private BufferedImage ori;
private BufferedImage res;
/**
* Create an ImageViewer show it on screen.
*/
public ImageViewer()
{
currentImage = null;
makeFrame();
}
// ---- 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; // 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);
showFilename(selectedFile.getPath());
showStatus("File loaded.");
frame.pack();
}
/**
* Close function: close the current image.
*/
private void close()
{
currentImage = null;
imagePanel.clearImage();
showFilename(null);
}
/**
* Quit function: quit the application.
*/
private void quit()
{
System.exit(0);
}
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 crop()
{
if(currentImage != null){
int width = currentImage.getWidth()/2;
int height = currentImage.getHeight()/2;
int startx = currentImage.getWidth()/2 - width / 2 - 1;
int starty = currentImage.getHeight()/2 - height / 2 - 1;
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 + startx, y + starty));
}
}
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 flipVertical()
{
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(width - x - 1, y));
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void flipHorizontal()
{
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, height - y - 1));
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void copyright()
{
if(currentImage != null)
{
int width = currentImage.getWidth() * 2;
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 % currentImage.getWidth(), y));
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
private void copybottom()
{
if(currentImage != null)
{
int width = currentImage.getWidth();
int height = currentImage.getHeight() * 2;
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 % currentImage.getHeight()));
}
}
currentImage = newImage;
imagePanel.setImage(currentImage);
frame.pack();
}
}
/**
* 'Darker' function: make the picture darker.
*/
private void makeDarker()
{
if(currentImage != null) {
currentImage.darker();
frame.repaint();
showStatus("Applied: darker");
}
else {
showStatus("No image loaded.");
}
}
/**
* 'Lighter' function: make the picture lighter
*/
private void makeLighter()
{
if(currentImage != null) {
currentImage.lighter();
frame.repaint();
showStatus("Applied: lighter");
}
else {
showStatus("No image loaded.");
}
}
/**
* 'threshold' function: apply the threshold filter
*/
private void threshold()
{
if(currentImage != null) {
currentImage.threshold();
frame.repaint();
showStatus("Applied: threshold");
}
else {
showStatus("No image loaded.");
}
}
/**
* 'Lighter' function: make the picture lighter
*/
private void showAbout()
{
JOptionPane.showMessageDialog(frame,
"ImageViewer\n" + VERSION,
"About ImageViewer",
JOptionPane.INFORMATION_MESSAGE);
}
// ---- support methods ----
/**
* Display a file name on the appropriate label.
* @param filename The file name to be displayed.
*/
private void showFilename(String filename)
{
if(filename == null) {
filenameLabel.setText("No file displayed.");
}
else {
filenameLabel.setText("File: " + filename);
}
}
/**
* Display a status message in the frame's status bar.
* @param text The status message to be displayed.
*/
private void showStatus(String text)
{
statusLabel.setText(text);
}
// ---- swing stuff to build the frame and all its components ----
/**
* Create the Swing frame and its content.
*/
private void makeFrame()
{
frame = new JFrame("ImageViewer");
makeMenuBar(frame);
Container contentPane = frame.getContentPane();
// Specify the layout manager with nice spacing
contentPane.setLayout(new BorderLayout(6, 6));
filenameLabel = new JLabel();
contentPane.add(filenameLabel, BorderLayout.NORTH);
imagePanel = new ImagePanel();
contentPane.add(imagePanel, BorderLayout.CENTER);
statusLabel = new JLabel(VERSION);
contentPane.add(statusLabel, BorderLayout.SOUTH);
// building is done - arrange the components and show
showFilename(null);
frame.pack();
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("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);
item = new JMenuItem("Darker");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { makeDarker(); }
});
menu.add(item);
item = new JMenuItem("Lighter");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { makeLighter(); }
});
menu.add(item);
item = new JMenuItem("Threshold");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { threshold(); }
});
menu.add(item);
//create edit menu
menu = new JMenu("Edit");
menubar.add(menu);
item = new JMenuItem("Smaller");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { makeSmaller(); }
});
menu.add(item);
item = new JMenuItem("Larger");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { makeLarger(); }
});
menu.add(item);
item = new JMenuItem("Crop (Just take the center)");
item.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) { crop(); }
});
menu.add(item);
item = new JMenuItem("Flip Vertical");
item.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {flipVertical();};
});
menu.add(item);
item = new JMenuItem("Flip Horizontal");
item.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {flipHorizontal();};
});
menu.add(item);
item = new JMenuItem("Make a copy to the right");
item.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {copyright();};
});
menu.add(item);
item = new JMenuItem("Make a copy to the bottom");
item.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {copybottom();};
});
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);
}
}
2. ImagePanel
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
/**
* Nama : Timothyus Tanner
* NRP : 05111740000103
* Kelas : PBO - A
* 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 Michael Kolling and David J. Barnes
* @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);
}
}
}
3. ImageFileManager
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
/**
* Nama : Timothyus Tanner
* NRP : 05111740000103
* Kelas : PBO - A
* 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 Michael Kolling and David J Barnes
* @version 2.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;
}
}
}
4. OFImage
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
/**
* Nama : Timothyus Tanner
* NRP : 05111740000103
* Kelas : PBO - A
* OFImage is a class that defines an image in OF (Objects First) format.
*
* @author Michael Kolling and David J. Barnes
* @version 1.1
*/
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);
}
/**
* Make this image a bit darker.
*/
public void darker()
{
int height = getHeight();
int width = getWidth();
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
setPixel(x, y, getPixel(x, y).darker());
}
}
}
/**
* Make this image a bit lighter.
*/
public void lighter()
{
int height = getHeight();
int width = getWidth();
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
setPixel(x, y, getPixel(x, y).brighter());
}
}
}
/**
* Perform a three level threshold operation.
* That is: repaint the image with only three color values:
* white, gray, and black.
*/
public void threshold()
{
int height = getHeight();
int width = getWidth();
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
Color pixel = getPixel(x, y);
int brightness = (pixel.getRed() + pixel.getBlue() + pixel.getGreen()) / 3;
if(brightness <= 85) {
setPixel(x, y, Color.BLACK);
}
else if(brightness <= 170) {
setPixel(x, y, Color.GRAY);
}
else {
setPixel(x, y, Color.WHITE);
}
}
}
}
}
Screenshoot
1. Gambar Awal
2. Flip Vertical
3. Flip Horizontal
4. Larger
5. Smaller
6. Copy the image to the right
7. Copy the image to the bottom
8. Crop