Question
The following code does not work properly, please modify it. -------------------------------------------- #include #include #include #include /* The RGB values of a pixel. */ struct Pixel
The following code does not work properly, please modify it.
--------------------------------------------
#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;
struct Comment *comments;
};
struct Comment {
char *text;
struct Comment *next;
};
/* 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;
char buffer[256];
struct Comment *comments = NULL;
while (fgets(buffer, sizeof(buffer), f) != NULL) {
if (buffer[0] == '#') {
// add a new comment
struct Comment *comment = malloc(sizeof(struct Comment));
comment->text = strdup(buffer + 1); // skip the "#" character
comment->next = comments;
comments = comment;
} else {
// parse the header
if (sscanf(buffer, "P3 %d %d %d ", &width, &height, &max) != 3) {
fprintf(stderr, "Error reading PPM header ");
return NULL;
}
break; // stop reading the header
}
}
if (comments != NULL) {
// reverse the linked list of comments to keep them in the original order
struct Comment *prev = NULL;
struct Comment *curr = comments;
while (curr != NULL) {
struct Comment *next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
comments = prev;
}
// allocate memory for the PPM image data
struct PPM *img = malloc(sizeof(struct PPM));
img->width = width;
img->height = height;
img->max = max;
img->pixels = malloc(width * height * sizeof(struct Pixel));
img->comments = comments;
// read the pixel data
for (int i = 0; i < width * height; i++) {
if (fscanf(f, "%d %d %d", &img->pixels[i].red, &img->pixels[i].green, &img->pixels[i].blue) != 3) {
fprintf(stderr, "Error reading PPM data ");
freePPM(img);
return NULL;
}
}
return img;
}
/* 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);
}
}
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;
}
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;
}
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]);
char message[256];
printf("Enter a message to encode: ");
scanf("%255[^ ]", message); // read up to 255 characters until a newline is encountered
/* Check that the message length is not too long */
int pixels_per_char = (oldimg->width * oldimg->height) / (strlen(message) + 1);
if (pixels_per_char < 3) {
fprintf(stderr, "Image too small to encode message ");
return 1;
}
if (pixels_per_char * (strlen(message) + 1) > oldimg->width * oldimg->height) {
fprintf(stderr, "Message too long to encode in image ");
return 1;
}
struct PPM *newimg = encode(message, oldimg);
if (newimg == NULL) {
fprintf(stderr, "Encoding failed ");
return 1;
}
free(newimg->pixels);
free(newimg);
free(oldimg->pixels);
free(oldimg);
} else if (argc == 4 && strcmp(argv[1], "d") == 0) {
/* Mode "d" - decode PPM */
struct PPM *oldimg = readPPM(argv[2]);
struct PPM *newimg = readPPM(argv[3]);
char *message = decode(oldimg, newimg);
if (message == NULL) {
fprintf(stderr, "Decoding failed ");
return 1;
}
printf("Decoded message: %s ", message);
free(message);
free(newimg->pixels);
free(newimg);
free(oldimg->pixels);
free(oldimg);
} else {
fprintf(stderr, "Usage: %s t|e|d
return 1;
}
void showPPMComments(const struct PPM *img)
{
struct Comment *comment = img->comments;
while (comment != NULL) {
printf("#%s", comment->text);
comment = comment->next;
}
}
return 0;
}
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started