Exception thrown: write access violation. Variable was nullptr

77 views Asked by At

I have to read a .pgm file for an assignment and decode the least significant bit in every byte to get some hidden text. I have the reading and writing code from the professor but when I try to read the file color has an issue being written to. I think I know how to actually get the hidden text out but the I/O always gives me trouble.

Thanks in advance for your help.

It wouldnt let me add the .pgm so i ranamed it as .png, so if you download it make sure to rename it to .pgm this is the .pgm image uploaded as a .png

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef unsigned char uchar;

/****************************************/
/* Clear PGM (XV) comments.             */
/****************************************/
void pgmCommentClear(FILE* disk) {
    uchar  ch;
    fread(&ch, 1, 1, disk);
    if (ch != '#') {
        fseek(disk, -1, SEEK_CUR);
        return;
    }
    do {
        while (ch != '\n') fread(&ch, 1, 1, disk);
    } while (ch == '#');
    pgmCommentClear(disk);
}

/****************************************/
/* Read PGM formatted image (1D array). */
/****************************************/
uchar* PGM_FILE_READ_1D(char* FileName, int* Width, int* Height, int* color) {
    int   pmax;
    char  ch;
    char  type[3];
    uchar* Image;
    FILE* disk;
    if ((disk = fopen(FileName, "rb")) == NULL) {
        return NULL;
    }
    fscanf(disk, "%s", type);
    if (!strcmp(type, "P6")) *color = 1;
    else *color = 0;
    fread(&ch, 1, 1, disk);
    pgmCommentClear(disk);
    fscanf(disk, "%d", Width);
    fscanf(disk, "%d", Height);
    fscanf(disk, "%d", &pmax);
    fread(&ch, 1, 1, disk);
    if (*color == 1) {
        Image = (uchar*)calloc(*Height * *Width * 3, sizeof(uchar));
        fread(Image, 1, (*Height * *Width * 3), disk);
    }
    else {
        Image = (uchar*)calloc(*Height * *Width, sizeof(uchar));
        fread(Image, 1, (*Height * *Width), disk);
    }
    fclose(disk);
    return Image;
}

/****************************************/
/* Write PGM formatted image (1D array).*/
/****************************************/
void PGM_FILE_WRITE_1D(char* FileName, uchar* Image, int Width, int Height, int color) {
    FILE* disk;
    disk = fopen(FileName, "wb");
    if (color == 1) fprintf(disk, "P6\n");
    else fprintf(disk, "P5\n");
    fprintf(disk, "%d %d\n", Width, Height);
    fprintf(disk, "255\n");
    if (color == 1) {
        fwrite(Image, 1, (Height * Width * 3), disk);
    }
    else {
        fwrite(Image, 1, (Height * Width), disk);
    }
    fclose(disk);
}

int main(int argc, char const* argv[]) {


    // do command line args stuff for extra credit
    //if (argv == 2) { }

    // read the file
    //int width = 876
    //int height = 594
    
    uchar* image = PGM_FILE_READ_1D("./hw10.pgm", 876, 594, 0);

    printf("%c", *image);

}
1

There are 1 answers

7
Anthony Kelly On BEST ANSWER

Pretty cool assignment, Ron Marsh ;-)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef unsigned char uchar;

/****************************************/
/* Clear PGM (XV) comments.             */
/****************************************/
void pgmCommentClear(FILE* disk) {
    uchar  ch;
    fread(&ch, 1, 1, disk);
    if (ch != '#') {
        fseek(disk, -1, SEEK_CUR);
        return;
    }
    do {
        while (ch != '\n') fread(&ch, 1, 1, disk);
    } while (ch == '#');
    pgmCommentClear(disk);
}

/****************************************/
/* Read PGM formatted image (1D array). */
/****************************************/
uchar* PGM_FILE_READ_1D(char* FileName, int* Width, int* Height, int* color) {
    int   pmax;
    char  ch;
    char  type[3];
    uchar* Image;
    FILE* disk;
    if ((disk = fopen(FileName, "rb")) == NULL) {
        return NULL;
    }
    fscanf(disk, "%s", type);
    if (!strcmp(type, "P6")) *color = 1;
    else *color = 0;
    fread(&ch, 1, 1, disk);
    pgmCommentClear(disk);
    fscanf(disk, "%d", Width);
    fscanf(disk, "%d", Height);
    fscanf(disk, "%d", &pmax);
    fread(&ch, 1, 1, disk);
    if (*color == 1) {
        Image = (uchar*)calloc(*Height * *Width * 3, sizeof(uchar));
        fread(Image, 1, (*Height * *Width * 3), disk);
    }
    else {
        Image = (uchar*)calloc(*Height * *Width, sizeof(uchar));
        fread(Image, 1, (*Height * *Width), disk);
    }
    fclose(disk);
    return Image;
}

/****************************************/
/* Write PGM formatted image (1D array).*/
/****************************************/
void PGM_FILE_WRITE_1D(char* FileName, uchar* Image, int Width, int Height, int color) {
    FILE* disk;
    disk = fopen(FileName, "wb");
    if (color == 1) fprintf(disk, "P6\n");
    else fprintf(disk, "P5\n");
    fprintf(disk, "%d %d\n", Width, Height);
    fprintf(disk, "255\n");
    if (color == 1) {
        fwrite(Image, 1, (Height * Width * 3), disk);
    }
    else {
        fwrite(Image, 1, (Height * Width), disk);
    }
    fclose(disk);
}

int main(int argc, char const* argv[]) {

    // do command line args stuff for extra credit
    char newMsg[100] = "";
    if (argc >= 2) 
        for (int i = 1; i < argc; i++) {
            strcat(newMsg, argv[i]);
            strcat(newMsg, " ");
        }
        else
            strcat(newMsg, "Greetings from the other side");
    strcat(newMsg, "\0");

    int width, height, color;
    
    // read the file
    uchar* image = PGM_FILE_READ_1D("./hw10.pgm", &width, &height, &color);
    printf("width = %d, height = %d, color = %d\n", width, height, color);

    // Read encoded message
    int size = width * height, bitCount = 8;
    uchar hiddenChar = 0;
    for (int i = 0; i < size; i++) {
        //shift least-significant bit left `bitCount` times and overlay onto `hidden`
        hiddenChar |= ((image[i] & 0x01) << --bitCount); 
        // After 8 bits we have the hidden byte
        if (bitCount == 0) {
            // If character is null terminator then we're done
            if (hiddenChar == 0) 
                break;
            // Print hidden character and reset
            printf("%c", hiddenChar);
            bitCount = 8;
            hiddenChar = 0;
        }
    }

    // Encode new message
    int len = strlen(newMsg) + 1;
    for (int i = 0; i < len; i++) 
        for (int j = 0; j < 8; j++) 
            if ( newMsg[i] & (0x01 << (7-j) ) )                 
                image[i * 8 + j] |= 0x01;
            else
                image[i * 8 + j] &= 0xfe;
    PGM_FILE_WRITE_1D("./hw10-out.pgm", image, width, height, color);

    return 0;
}