Lab 2: Image Displayer 3001
Overview
In this assignment you will implement a Graphical User Interface (GUI) for your solution to Lab 1. Additionally, you will add functionality for two new binary file formats, .ibig, .isml, that can reduce the space taken by a great deal. Finally, you will create a custom Exception class that will be thrown when problems with the input data are encountered.
GUI
Your GUI must have separate buttons to use for saving each file format, for loading the image, and for quitting the program. You will
use a FileChooser
to obtain the File
objects to read and write, and will have a single Canvas to draw the image onto.
An example of the GUI might look like this:
You should, at a minimum, have the same six Buttons and use the same text as shown above for the Buttons, but the rest of the design and layout is up to you.
Integer Binary Format
This binary format stores all the image information as binary integer values.
- The first integer in the file represents the width of the image. This value must be positive.
- The second integer in the file represents the height of the image. This value must be positive.
- The remaining integer values represent the pixel values for the image. These values must either be
0
or1
. - There must be a total of \( width \times height + 2 \) integers in the file.
Files in this format must use .ibig
file extension.
Bit Binary Format
This binary format uses one bit for each pixel in the image.
- The first integer in the file represents the width of the image. This value must be positive.
- The second integer in the file represents the height of the image. This value must be positive.
- The remaining byte values store the pixel values for the image.
- If the \( width \times height \) of the image is not divisible by 8, the unused bits in the last byte must all be zero.
Files in this format must use .isml
file extension.
Overview of bit operators
The following operators are helpful for manipulating bits:
|
— bitwise OR operator&
— bitwise AND operator~
— bitwise NOT operator^
— bitwise XOR operator>>
— logical right shift operator<<
— left shift operator
We can represent binary literals by prefixing the number with 0b
. E.g.,
0b00000001
is equal to integer value1
since the 1's place has a 1 in it and everything else is 0.0b00001111
is equal to integer value15
since the 1's, 2's, 4's and 8's places have 1 in them and the 16's, 32's, 64's, and 128's places have 0 in them. (15 == 1 + 2 + 4 + 8)
The following are all true:
0b00111100 | 0b11001100 == 0b11111100;
0b00111100 & 0b11001100 == 0b00001100;
0b00111100 ^ 0b11001100 == 0b11110000;
~0b00111100 == 0b11000011;
0b00001000 >> 2 == 0b00000010;
0b00001000 << 3 == 0b01000000;
Therefore, if we want to get the third bit from the right as an integer, we can do:
int bitValue = (byteValue >> 2) & 0b00000001;
(byteValue >> 2)
moves the bit from the 4's place to the 1's place.(result) & 0b00000001
ensures all but the bit at the 1's place is zero.
If we want to place the value of an integer (with value of either 0
or 1
) in the 8's
place and not disrupt the other bit values in the other places, we can do:
byteValue = ((intValueForPixel & 0b00000001) << 3) | (byteValue & 0b11110111);
(intValueForPixel & 0b00000001)
ensures all but the bit at the 1's place is zero.((result) << 3)
moves the bit from the 1's place to the 8's place.(byteValue & 0b11110111)
ensures that the bit at the 8's place is zero.- Here the value on the left contains zeros for every bit except at the 8's place and the value on the right keeps all the values original in byteValue except the bit at the 8's place.
(result1) | (result2)
places a 1 in the 8's place ifintValueForPixel
was1
. Otherwise, the 8's place will contain0
.
Software Design
You should use your Image
and PixelCluster
classes from Lab 1 as the basis for the logic for this program. In addition,
you will need to create, organize, and display all of your GUI components and link them to the rest of your program. This should be
done in your main driver class using helper methods to break up the work.
InvalidFormatException
You must create a custom Exception
class that will be thrown in place of an IllegalArgumentException
when the exception is
caused not by an incorrect argument, but bad data. For example, if you are reading a block text file and the Unicode value
does not match any of the PixelCluster enum values, the argument (a String
) is fine, but the data formatting is not.
The InvalidFormatException
should have the following methods:
InvalidFormaException()
— A no-parameter constructorInvalidFormaException(String message)
— A constructor that takes a custom message
Main
Class
Your Main
class is where you will set up your GUI and kick off your program. It must extend the JavaFX Application class and have, at a minimum, the following methods:
static void main(String[] args)
— The main method of the program. It's sole purpose is to call the staticlaunch
methodvoid start(Stage stage)
— This is where theScene
andStage
will be assembled and shown to the user.Scene buildGUI()
— This is where the individual components will be created and added to the top-level container.- You should make use of helper methods to break up the work done in this method.
- The top-level container should be added to a new
Scene
and thatScene
is what will be returned to thestart()
method
Exception Handling
If any problems are encountered with reading the input files or writing the output file, the program should display a useful error message using Alert objects. The program should not print anything to the console, nor should it crash or display any exceptions.
Acknowledgement
This laboratory assignment, developed by Prof. Sean Jones and Dr. Chris Taylor.