Week 3 Lab: Image Manipulator 3000

Objectives

Resources

Overview

In this assignment you will be developing an image manipulation program. The remaining laboratory assignments will build on this one, allowing you to improve your initial submission based on feedback from your instructor. The program itself will be capable of reading and writing multiple image formats including .jpg, .png, and a custom format: .msoe files. The program will also be able to apply simple transformations to the image like:

The transformations are applied to the image that appears on the screen (rather than the image originally loaded from the file) so that multiple transformations can be applied. For example, the user should be able to create a negative grayscale image by clicking both buttons.

Assignment

This assignment has been designed to provide numerous ways in which the program may be expanded. Students are encouraged to use their creativity to implement additional functionality beyond the requirements of the assignment; however, it is important to complete the required functionality before getting too carried away.

User Interface

Figure 1: User Interface1)

In short, you must implement the following functionality:

All of your classes should be placed in a package whose name matches your MSOE username.

Details

Handler Methods

Your user interface does not need to match Figure 1 but does need to facilitate all the functionality in an intuitive way. Additionally, you must at a minimum have the same five Buttons with the same text as Figure 1. If you would like to add keyboard shortcuts to the Buttons, see Accelerators below. You must incorporate the following methods into your design:

You will use FXML for this lab. WHen you are constructing your lab, keep in mind the MVC (Model, View, Controller) architecture. You should only interact with the user from your Controller class. Additionally, you should never print anything to the console. Use Alerts to inform the user of any error that occurs.

.msoe File Format

The custom .msoe file format is a text based file format for storing images. It is designed to be easy to load and save, but results in comparatively large file sizes. The contents of a very small image of a white-on-black + symbol is shown below:

MSOE
3 3
#000000 #FFFFFF #000000
#FFFFFF #FFFFFF #FFFFFF
#000000 #FFFFFF #000000

Your program should be able to load hamburger.msoe image in the images folder of the repository.

Loading and Saving Images

The program must support loading and saving .jpg, .png, and .msoe image file formats. The open button will open a FileChooser dialog that will allow the user to select the file to be loaded (showOpenDialog()). The program will use the extension to determine the format of the file and load the image. If the file extension is not supported or the file contents does not match the file extension, the program will display an error message. Pressing the reload button will reload the most recently loaded image.

The save button will open a FileChooser dialog box that will allow the user to select the destination folder and type in the filename and extension (showSaveDialog()). The program will then write the image to that file using the file format that matches the file extension. If an unsupported file extension is entered, the program will display an error message without attempting to save the image.

Both the open and save dialogs should default to an images folder in the project (at the same level as the src folder). You'll need to create this folder in your project.

You are responsible for writing your own ImageIO class for loading and saving images. The class must have the following public class methods:

If the extension on the file passed to either of these methods is .msoe then the appropriate private class method below is called to do the actual work.

Both read() and write() must throw an IllegalArgumentException if the path passed in has a file extension that specifies an unsupported image format.

You may use the ImageUtil class in the ImageUtil.jar to read and write files in the .jpg and .png formats. You must implement your own code to read and write .msoe files.

Grayscale

This transformation converts the image into a grayscale image. If the image is already grayscale, the transformation has no affect. In this transformation, the RGB components of each pixel are replaced with a single value. The replacement value can be calculated as: gray = 0.21R + 0.71G + 0.07B more info.

Grayscale

Grayscale Example

Negative

This transformation converts the image into a photo negative of the original image. In this transform, each RGB component is replaced with 1.0 - original value. Thus, an RGB value of (1.0, 1.0, 0.0) would become (0.0, 0.0, 1.0). more info.

Negative

Negative Example

Exception Handling

There are a number of situations that could cause your program to throw an exception. For example, if the file is not found, cannot be opened, or contains incorrectly formatted data, it is likely that an exception will be thrown. In these cases, the program should display a useful message.

You should not catch an exception, only to throw another exception. Use conditionals (if, if/else, switch) to determine if a value or parameter is incorrect or dangerous (if it could cause an exception to be thrown), then throw your own exception.

Just For Fun

There are many additional enhancements that could build on the required functionality. You are encouraged to enhance this application using your creativity. A number of potential enhancements are included below; however, you should not feel limited to these suggestions.

Accelerators

For each action in the program, there will be a corresponding keyboard shortcut that allows the user to operate the program without using a mouse. In JavaFX, these keyboard shortcuts are best implemented using what is called Accelerators.

An accelerator is a keyboard shortcut that triggers an action regardless of which control currently has focus. Unlike mnemonics, accelerators are not tied to a specific UI control being focused or visible, and they behave consistently across platforms. This makes accelerators the preferred mechanism for keyboard shortcuts in JavaFX applications, especially on macOS.

In JavaFX, an accelerator consists of:

The KeyCombination can be as simple as a single key, or it can include modifier keys such as Control, Shift, Alt, or Meta (Command on macOS). For example, the amazing IntelliJ shortcut used to automatically format code: Ctrl + Alt + Shift + L can be represented in JavaFX as follows:

        KeyCombination keyCombination = new KeyCodeCombination(
            KeyCode.L,
            KeyCombination.CONTROL_DOWN,
            KeyCombination.ALT_DOWN,
            KeyCombination.SHIFT_DOWN
        );

To register this key combination as an accelerator, it must be added to the current Scene along with the action it should perform. For example, to trigger a format() method when the shortcut is pressed:

        scene.getAccelerators().put(
            keyCombination,
            () -> format()
        );

Once added, JavaFX will listen for the specified key combination and execute the associated action whenever it is pressed, regardless of which control currently has focus. All accelerators must be registered with the active Scene. If a shortcut is not added to the Scene’s accelerator map, JavaFX will not recognize it.

Use the following key mappings for the Accelerators:

Acknowledgment

This laboratory assignment was developed by Dr. Chris Taylor.

1) The label at the bottom center of the window is not required but is the first enhancement suggested in the Just for Fun section.
See your professor's instructions for details on submission guidelines and due dates.