!note Mistral Nemo 2407 (llama.cpp, Q4_K_M) !:temperature 0 !:max_tokens 10000 !context Lab4_Q3.txt !context stego_lsb.c !user Please complete this assignment. !assistant Here's a completed version of the `stego_lsb.c` program with the required functions implemented. I've added comments to explain each step and used bitwise operations to manipulate the pixel values for LSB steganography. ```c #include <stdio.h> #include <stdlib.h> #define WIDTH 512 #define HEIGHT 512 // Function to read a PGM image in text format. int readPGMText(const char *filename, unsigned char *pixels, int width, int height) { FILE *file = fopen(filename, "r"); if (!file) { perror("Error opening file"); return 1; } char line[1024]; fgets(line, sizeof(line), file); // Skip the first line (P2) fgets(line, sizeof(line), file); // Skip the second line (comment) int w, h, max_val; fscanf(file, "%d %d\n%d\n", &w, &h, &max_val); if (w != width || h != height) { printf("Error: Image dimensions do not match\n"); return 1; } for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) { fscanf(file, "%hhu", &pixels[i * width + j]); } } fclose(file); return 0; } // Function to write a PGM image in text format. int writePGMText(const char *filename, unsigned char *pixels, int width, int height) { FILE *file = fopen(filename, "w"); if (!file) { perror("Error opening file"); return 1; } fprintf(file, "P2\n# Created by stego_lsb.c\n%d %d\n255\n", width, height); for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) { fprintf(file, "%hhu ", pixels[i * width + j]); } fprintf(file, "\n"); } fclose(file); return 0; } // Function to write a PGM image in binary format. int writePGMBinary(const char *filename, unsigned char *pixels, int width, int height) { FILE *file = fopen(filename, "wb"); if (!file) { perror("Error opening file"); return 1; } fprintf(file, "P5\n# Created by stego_lsb.c\n%d %d\n255\n", width, height); fwrite(pixels, sizeof(unsigned char), width * height, file); fclose(file); return 0; } // Function to hide a secret image using the 4-bit LSB steganography algorithm. void embedLSB(unsigned char *coverPixels, unsigned char *secretPixels, int width, int height) { for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) { // Get the 4 MSBs of the cover pixel and the 4 LSBs of the secret pixel unsigned char cover_msb = (coverPixels[i * width + j] & 0xF0); unsigned char secret_lsb = (secretPixels[i * width + j] & 0x0F); // Combine them to create the stego pixel coverPixels[i * width + j] = (cover_msb | secret_lsb); } } } // Function to extract the secret image using 4-LSB steganography algorithm. void extractLSB(unsigned char *coverPixels, unsigned char *outputPixels, int width, int height) { for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) { // Get the 4 LSBs of the stego pixel (which are the 4 MSBs of the secret pixel) unsigned char secret_msb = (coverPixels[i * width + j] & 0x0F); // Set the 4 LSBs of the secret pixel to 0 outputPixels[i * width + j] = (secret_msb << 4); } } } int main() { char cover_image[] = "baboon.pgm"; char secret_image[] = "farm.pgm"; char stego_image[] = "stego_image_bin.pgm"; char extracted_secret[] = "extracted_secret.pgm"; unsigned char *coverPixels, *secretPixels, *outputPixels; int coverWidth = WIDTH, coverHeight = HEIGHT, secretWidth = WIDTH, secretHeight = HEIGHT; // Using malloc, dynamically request exact memory space, referenced by coverPixels, to store the cover image pixel values. coverPixels = malloc(coverWidth * coverHeight); if (!coverPixels) { perror("Error allocating memory for coverPixels"); return 1; } // Read the cover image file (text PGM) and store its pixels in 'coverPixels' referenced memory space. if (readPGMText(cover_image, coverPixels, coverWidth, coverHeight)) { return 1; } // Using malloc, dynamically request exact memory space, referenced by 'secretPixels', to store the secret image pixel values. secretPixels = malloc(secretWidth * secretHeight); if (!secretPixels) { perror("Error allocating memory for secretPixels"); free(coverPixels); return 1; } // Read the secret image file (text PGM) and store its pixels in 'secretPixels' referenced memory space. if (readPGMText(secret_image, secretPixels, secretWidth, secretHeight)) { free(coverPixels); free(secretPixels); return 1; } // Check if the dimensions of both images match, exit if they don't. if (coverWidth != secretWidth || coverHeight != secretHeight) { printf("Error: Image dimensions do not match\n"); free(coverPixels); free(secretPixels); return 1; } // Call the function embedLSB to embed the secret image into the cover image. embedLSB(coverPixels, secretPixels, coverWidth, coverHeight); // The stego image pixels are stored in 'coverPixels' referenced memory space. // Save the stego image into binary format to stego_image_bin.pgm if (writePGMBinary(stego_image, coverPixels, coverWidth, coverHeight)) { free(coverPixels); free(secretPixels); return 1; } // Using malloc, dynamically request exact memory space, referenced by 'outputPixels', to store the extracted secret image outputPixels = malloc(secretWidth * secretHeight); if (!outputPixels) { perror("Error allocating memory for outputPixels"); free(coverPixels); free(secretPixels); return 1; } // Call the function extractLSB to extract the secret image from the stego image extractLSB(coverPixels, outputPixels, coverWidth, coverHeight); // Save the extracted secret image in a text format to extracted_secret.pgm if (writePGMText(extracted_secret, outputPixels, secretWidth, secretHeight)) { free(coverPixels); free(secretPixels); free(outputPixels); return 1; } free(coverPixels); free(secretPixels); free(outputPixels); return 0; } ``` To compile and run the program, use the following commands: ```sh gcc -o stego_lsb stego_lsb.c ./stego_lsb ``` This will generate the `stego_image_bin.pgm` and `extracted_secret.pgm` files in the same directory as the executable.