Question: The problem Writing a simple steganography program in C, called steg. steg can operate in two modes encode and decode selected by the first command-line
The problem
Writing a simple steganography program in C, called steg. steg can operate in two modes encode and decode selected by the first command-line argument being e or d. An RGB colour bitmap image consists of a grid of pixels, each of which has red, green and blue colour values. To encode text inside an image, your program will replace the red value in successive random pixels in the image with characters from the text, outputting a new image. When encoding, your program will be invoked as: ./steg e old.ppm >new.ppm It must prompt for a message to encode, and output the new image to stdout (in this case we have redirected it to a file). To decode the text, your program will compare the new image with the old image, and extract characters from the new one where it differs from the old one. When decoding, your program will be invoked as: ./steg d old.ppm new.ppm It must decode the message and output the hidden text to stdout.
The PPM image format You will work with Plain PPM format images. This is one of a family of simple open source image formats, designed to be read and written easily by C programs. See the PPM specification for full details of PPM and Plain PPM. A Plain PPM file consists of ASCII text: P3 # comment1 # ... # commentN width height max r1 g1 b1 r2 g2 b2 r3 g3 b3 ...
Requirements
2 - PPM functions Implement in steg.c the following functions. You may also write additional helper functions or type declarations if you like. The template includes some already, e.g. struct Pixel and readPPM, but you can rename or remove these provided you implement struct PPM, getPPM, showPPM, encode and decode. 2a - (2 points) Reading PPM files struct PPM *getPPM(FILE *f); To return a new struct PPM, containing the PPM image read from open file f. Use the fscanf function to read numbers from the file. Once you know width and height, construct a dynamic array of the appropriate size. Don't worry about handling comments in the PPM file for now. 2b - (2 points) Writing PPM files void showPPM(const struct PPM *img); To output the PPM image img to stdout (e.g. by using printf), following the syntax in the PPM specification. You should test this function by using it to write out an image loaded with getPPM. The template code's main function has an extra t t mode for this. 2c - (2 points) Encode data struct PPM *encode(const char *text, const struct PPM *img); To return a copy of PPM image img with message text hidden in its red pixel values. You will need to make it replace successive random red pixels with the characters from the message. How you select pixels is up to you, but make sure that the pixels are chosen in a consistent order (e.g. left to right, top to bottom) and enough pixels are selected to encode all of the message. 2d - (2 points) Decode data char *decode(const struct PPM *oldimg, const struct PPM *newimg); to return a new string containing the message hidden in the red pixel values of PPM image newimg, by comparing it with the red pixel values of PPM image oldimg. The length of the string that it allocates and returns will depend on the length of the message. You may impose a limit on the maximum length of a decoded message if this makes the implementation easier.
=====================================================================================
#include
#include
#include
#include
/* The RGB values of a pixel. */
struct Pixel {
int red;
int green;
int blue;
};
/* An image loaded from a PPM file. */
struct PPM {
int width;
int height;
int max;
struct Pixel *pixels;
};
/* Reads an image from an open PPM file.
* Returns a new struct PPM, or NULL if the image cannot be read. */
struct PPM *getPPM(FILE * f)
{
int width, height, max;
if (fscanf(f, "P3 %d %d %d ", &width, &height, &max) != 3) {
fprintf(stderr, "Error reading PPM header ");
return NULL;
}
}
/* Write img to stdout in PPM format. */
void showPPM(const struct PPM *img)
{
/* TODO: Question 2b */
}
/* Opens and reads a PPM file, returning a pointer to a new struct PPM.
* On error, prints an error message and returns NULL. */
struct PPM *readPPM(const char *filename)
{
/* Open the file for reading */
FILE *f = fopen(filename, "r");
if (f == NULL) {
fprintf(stderr, "File %s could not be opened. ", filename);
return NULL;
}
/* Load the image using getPPM */
struct PPM *img = getPPM(f);
/* Close the file */
fclose(f);
if (img == NULL) {
fprintf(stderr, "File %s could not be read. ", filename);
return NULL;
}
return img;
}
/* Encode the string text into the red channel of image img.
* Returns a new struct PPM, or NULL on error. */
struct PPM *encode(const char *text, const struct PPM *img)
{
/* TODO: Question 2c */
return NULL;
}
/* Extract the string encoded in the red channel of newimg, by comparing it
* with oldimg. The two images must have the same size.
* Returns a new C string, or NULL on error. */
char *decode(const struct PPM *oldimg, const struct PPM *newimg)
{
/* TODO: Question 2d */
return NULL;
}
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
