2
votes

So ive already read a number of the questions that relate to this but none of them have solved my problem. Im currently attempting to read in a P6 ppm file (Its a binary file). My current code is

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

struct pixel {
    char red;
    char green;
    char blue;
};

int main(int argc, char **argv)
{
    char type[3];
    int numRow, numCol, maxNum;
    FILE *oldFile, *newFile;
    struct pixel currentPixel;
    char buffer[5];

    oldFile = fopen(argv[1], "rb");
    if(oldFile == NULL) {
        fprintf(stderr, "Could not open file %s for reading in binary", argv[1]);
        return 0;
    }
    fscanf(oldFile, "%2s", type);
    type[2] = '\0';
    if(strcmp(type, "P6") != 0) {  //Make sure we have a P6 file
        printf("This file is not of type P6");
        return 0;
    }

    newFile = fopen(argv[2], "wb");
    fprintf(newFile, "%s\n", type);
    /*Read number of columns
    rows and
    The max number that can represent a colour*/
    fscanf(oldFile, "%d", &numCol);
    fscanf(oldFile, "%d", &numRow);
    fscanf(oldFile, "%d", &maxNum);
    /*Print the information to newFile*/
    fprintf(newFile, "%d %d\n", numCol, numRow);
    fprintf(newFile, "%d\n", maxNum);
    fseek(oldFile, 1, SEEK_CUR);

    fread(&currentPixel, sizeof(struct pixel), 1, oldFile);
    printf("%c %c %c", currentPixel.red, currentPixel.green, currentPixel.blue);

    fclose(newFile);
    fclose(oldFile);
    return 0;
}

So the beginning works and my newFile contains the lines P6, 3 3, and 255. I then try to read in the actual pixels with the fread line. This is where it fails and im not sure why. It currently prints out two question marks inside of a diamond. I am currently only trying to read in the first three numbers which make up one pixel (one red component one green and one blue).

I also have a P3 file of the same picture and the P3 file looks like:

 P3

3 3

255

  0 255 255   0   0   0   0   0 255

255   0 255 100 100 100 255   0   0

255 255   0 255 255 255   0 255   0

So the binary file should be set up like this but just in binary format. When i type in

od -c binaryImage.ppm

I get

0000000   P   6  \n   3       3  \n   2   5   5  \n  \0 377 377  \0  \0
0000020  \0  \0  \0 377 377  \0 377   X   X   X 377  \0  \0 377 377  \0
0000040 377 377 377  \0 377  \0
0000046

Im not sure why my fread function is not working.Not sure if relevant but i am compiling on Linux Ubuntu with

gcc -Wall rotate.c -o rotate

1
@WeatherVane The first three lines are regular text. Reading those with fscanf works fine but after that we need to read using fread since the rest of the file is written in binaryTheQAGuy
Why are you printing RGB values as characters (%c) instead as numbers (%d)? That's the reason you get strange symbols in the output.Bruno Ribeiro
@BrunoBellucci Thats a good question. I changed my code so instead of red, green and blue being char i made them int's. It now prints out 16776960 0 -16711681TheQAGuy
No. Your pixel values should be char, but you need print them as integers.Bruno Ribeiro
@BrunoBellucci That prints out 0 -1 -1TheQAGuy

1 Answers

2
votes

You are printing RGB values as characters instead as numbers. Keep them as unsigned char (because they have values between [0-255]) in the structure, but use %d when printing. You should use printf as follows:

printf("%d %d %d", currentPixel.red, currentPixel.green, currentPixel.blue);

Also I recommend do not use a structure to read the RGB values because the compiler will probably add a padding byte to align the structure to the machine word (e.g. 32 bits). In 32 bits systems, you will read 4 bytes. You can check this printing the sizeof(struct pixel). To read more about structure alignment you could check the Wikipedia article Data Structure Alignment.

Instead a struct, use a char array:

unsigned char currentPixel[3];
...
fread(currentPixel, 3, 1, oldFile);
printf("%d %d %d", currentPixel[0], currentPixel[1], currentPixel[2]);

Also, if you need to read the entire image, create an array of unsigned char with size number of pixels x 3. The 3 is the number of bytes for the RGB tuple. If the PPM format include some padding at the end of each line, you need to consider this too.