Question: Complete the following code fill ALL THET ODO ========================================= #include #include #include #include /* The RGB values of a pixel. */ struct Pixel { int
Complete the following code fill ALL THET ODO
=========================================
#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)
{
printf("P3 %d %d %d ", img->width, img->height, img->max);
for (int i = 0; i < img->width * img->height; i++) {
printf("%d %d %d ", img->pixels[i].red, img->pixels[i].green, img->pixels[i].blue);
}
}
/* 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)
{
int text_len = strlen(text);
int pixels_per_char = (img->width * img->height) / (text_len + 1);
if (pixels_per_char < 3) { // at least 3 pixels per character to encode
fprintf(stderr, "Image too small to encode message ");
return NULL;
}
if (pixels_per_char * (text_len + 1) > img->width * img->height) { // message too long to encode
fprintf(stderr, "Message too long to encode in image ");
return NULL;
}
struct PPM *newimg = malloc(sizeof(struct PPM));
newimg->width = img->width;
newimg->height = img->height;
newimg->max = img->max;
newimg->pixels = malloc(newimg->width * newimg->height * sizeof(struct Pixel));
memcpy(newimg->pixels, img->pixels, newimg->width * newimg->height * sizeof(struct Pixel));
srand(time(NULL));
for (int i = 0; i < text_len; i++) {
int j = i * pixels_per_char + rand() % pixels_per_char;
newimg->pixels[j].red = (unsigned char)
text[i];
}
return newimg;
}
/* 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)
{
int pixels_per_char = (oldimg->width * oldimg->height) / (strlen(MESSAGE) + 1);
int max_msg_len = pixels_per_char - 1; // maximum length of message that can be encoded in one group of pixels
char *msg = malloc(max_msg_len * (strlen(MESSAGE) + 1) + 1); // allocate space for the decoded message
int msg_idx = 0;
for (int i = 0; i < strlen(MESSAGE); i++) {
int j = i * pixels_per_char + rand() % pixels_per_char;
char c = newimg->pixels[j].red ^ oldimg->pixels[j].red; // decode the character by XORing the red values
if (c == '\0') { // end of message reached
break;
}
if (msg_idx >= max_msg_len * (strlen(MESSAGE) + 1)) { // message too long to decode
fprintf(stderr, "Message too long to decode ");
free(msg);
return NULL;
}
msg[msg_idx++] = c;
}
msg[msg_idx] = '\0'; // null-terminate the message
return msg;
}
/* TODO: Question 3 */
int main(int argc, char *argv[])
{
/* Initialise the random number generator, using the time as the seed */
srand(time(NULL));
/* Parse command-line arguments */
if (argc == 3 && strcmp(argv[1], "t") == 0) {
/* Mode "t" - test PPM reading and writing */
struct PPM *img = readPPM(argv[2]);
showPPM(img);
} else if (argc == 3 && strcmp(argv[1], "e") == 0) {
/* Mode "e" - encode PPM */
struct PPM *oldimg = readPPM(argv[2]);
/* TODO: prompt for a message from the user, and read it into a string */
struct PPM *newimg;
/* TODO: encode the text into the image with encode, and assign to newimg */
/* TODO: write the image to stdout with showPPM */
} else if (argc == 4 && strcmp(argv[1], "d") == 0) {
/* Mode "d" - decode PPM */
struct PPM *oldimg;
/* TODO: get original file filename from argv, load it with
readPPM, then assign to oldimg */
struct PPM *newimg;
/* TODO: get encoded file filename from argv, load it with
readPPM, then assign to newimg */
char *message;
/* TODO: decode the encodedPPM with the comparisonPPM and assign to message */
/* TODO: print the decoded message to stdout */
} else {
fprintf(stderr, "Unrecognised or incomplete command line. ");
return 1;
}
return 0;
}
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
