!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.