You are expected to complete this assignment individually. If you need help, you are invited to come to office hours and/or ask questions on piazza. Clarification questions about the assignments may be asked publicly. Once you have specific bugs related to your code, make the posts private.
This homework has several exercises. We are also providing you with some resources on printf and error handling for this assignment.
You should submit four files for this assignment ( hw3.h, hw3.c, hw3_main.c, and Makefile) in your subversion repository as directed below.
Steganography is the art and science of writing hidden messages in such a way that no one apart from the intended recipient knows of the existence of the message; this is in contrast to cryptography, where the existence of the message itself is not disguised, but the content is obscured. . .
Generally, a steganographic message will appear to be something else: a picture, an article, a shopping list, or some other message. This apparent message is the covertext. For instance, a message may be hidden by using invisible ink between the visible lines of innocuous documents.
The advantage of steganography over cryptography alone is that messages do not attract attention to themselves, to messengers, or to recipients. An unhidden coded message, no matter how unbreakable it is, will arouse suspicion and may in itself be incriminating, as in countries where encryption is illegal.
For this assignment, you will construct a very basic steganographic system by implementing a pair of data transformations. These two transformations provide the means to hide and later extract an approximation of a secret image in a cover image.
In the image below, the original image is on the left, and the image we are trying to store is in the middle. Notice that the image we are hiding is black and white. If we were to allow storing rich images, that would be too much information to hide without altering the look of the original picture. Instead, we are going to change it in a way that is visually indistinguishable from the original picture. The picture on the right is after the encoding of the black and white picture into the color picture.
We will encode one bit of information for each r, g, and b value. Let's take the red value. If the red value is "light" (more than half its saturation value), then we will make sure the red value of the new image is odd. If it is "dark" (less than half its saturation value), then it will be forced to be even.
To extract this same value, we determine whether or not the pixel in the encoded image is odd or even. If it is even, then red is set to 0. If it is odd, then red is set to the maximum value.
Because you are adding a second set of files to your directory, you need to add a second target to your Makefile. In your makefile, add another two lines (with a space between these and the ones already there).
hw3: hw3.h hw3.c hw3_main.c clang -Wall -o hw3 hw3.c hw3_main.c
Now you need to make the skeleton code so that your program will minimally execute. You must do this in case you do not complete your assignment. Our testing infrastructure needs to compile and execute even if you did not complete the entire assignment.
/* surface_area_cylinder * Calculates the surface area of a cylinder given height and radius * inputs: height, radius * output: double */ double surface_area_cylinder(double height, double radius);
double surface_area_cylinder(double height, double radius) { return 0.0; }
int main() { surface_area_cylinder(1.0, 5.0); // add the rest of the function calls here }
In this exercise, you will be provided images that you need to read into r,g,b arrays. You have also been provided functions that will read and write PNG files. The functions are declared and implemented in hw3_provided.h and hw3_provided.c, respectively. You should already have those files from your completed warmup.
void hide_image( unsigned int ref_r[ROWS][COLS], unsigned int ref_g[ROWS][COLS], unsigned int ref_b[ROWS][COLS], unsigned int hid_r[ROWS][COLS], unsigned int hid_g[ROWS][COLS], unsigned int hid_b[ROWS][COLS], unsigned int res_r[ROWS][COLS], unsigned int res_g[ROWS][COLS], unsigned int res_b[ROWS][COLS], unsigned int height, unsigned int width);
In this exercise, you will write the code to hide an image. You are using three images. The first, the reference image, is where you will hide the image. The second, hidden image, is the image you want to hide. The third, result, is the resulting image. All images are the same height and width. Height and width must be smaller than ROWS and COLS, respectively.
Because we haven't covered structs yet, each image is annoyingly split up into three double-arrays, each storing the values for one color component of the pixel. This will change once we cover structs.
You are going to do this by changing the lowest digit by no more than 1. If the hidden image has a value at least 128, then the value in the resulting image needs to be odd. If the reference picture's value is currently even, you need to increase the value by 1 in the resulting image. If the hidden image has a value less than 128, then the value of the resulting image needs to be even. If the current value in the reference image is odd, then you need to decrease the value by 1 in the resulting image.
The reference and hidden images must not change - those are input parameters. Only the result should change.
void extract_image( unsigned int res_r[ROWS][COLS], unsigned int res_g[ROWS][COLS], unsigned int res_b[ROWS][COLS], unsigned int hid_r[ROWS][COLS], unsigned int hid_g[ROWS][COLS], unsigned int hid_b[ROWS][COLS], unsigned int height, unsigned int width);
Our encryption scheme loses data - if you have an image that you want to hide that has many colors, those will be collapsed into a very small set of colors. That is okay and expected.
In this part, you will extract the hidden image (which may or may not be identical to the original hidden image). You will look at each pixel's r,g, and b values. If the value is odd, then the resulting image value is 255. If it is even, then the resulting image value is 0.
res is the image that is encoded. This is an in parameter. hid is where you will put the image you extract. This is the hidden image. It is an out parameter.
void encode(char *ref_filename, char *hid_filename, char *enc_filename); void decode(char *enc_filename, char *hid_filename);
$ svn add hw3.h hw3.c hw3_main.c
$ svn commit -m "hw3 complete"